'  ____         ____
' | __ )  __ _ / ___|___  _ __
' |  _ \ / _` | |   / _ \| '_ \
' | |_) | (_| | |__| (_) | | | |   --= A BaCon BASIC-to-C converter =--
' |____/ \__,_|\____\___/|_| |_|
'
' Peter van Eerten - March 2009/April 2011. License: GPL version 3.
'
'----------------------------------------------------------------------------------------------
' CREDITS:
'   - James C. Fuller for endless testing and patiently pointing to many issues
'   - John Spikowksi for giving some hints to improve the language
'   - Vovchik for providing ideas, programs and hints
'
'----------------------------------------------------------------------------------------------
'
' Though BaCon is much more powerful than KSH or BASH, this program follows the same structure
' and approach as the existing shell script implementations where possible.
'
' The reason for this is maintainability and consistency: a bug should show up in all versions
' and should be solved in all versions.
'
'----------------------------------------------------------------------------------------------
' GLOBAL INITIALIZATIONS
'----------------------------------------------------------------------------------------------

TRAP LOCAL

' Lower bound of array starts with 1
OPTION BASE 1

' Prevent parse errors
OPTION COLLAPSE TRUE

' Version of BACON
CONST g_VERSION$ = "1.0 build 22"

' Link flags
IF INSTR(OS$, "OSF1") OR INSTR(OS$, "BSD") THEN g_LDFLAGS$ = "-lm"
ELSE g_LDFLAGS$ = "-lm -ldl"

'  Solaris
IF INSTR(OS$, "SunOS" ) THEN g_LDFLAGS$ = CONCAT$(g_LDFLAGS$, " -lnsl -lsocket")

' Global to define '$'-replacement
CONST g_STRINGSIGN$ = "__b2c__string_var"

'----------------------------------------------------------------------------------------------

FUNCTION Check_Declared(STRING filename$, STRING v$, NUMBER position)

    LOCAL txt$, needle$
    LOCAL expr
    LOCAL thefile TYPE FILE*

    needle$ = REPLACE$(v$, "*", "\\*")

    OPEN filename$ FOR READING AS thefile

    SEEK thefile OFFSET position

    WHILE NOT(ENDFILE(thefile)) DO

        READLN txt$ FROM thefile
        IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
            expr = REGEX(txt$, "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING")
	    IF ISTRUE(expr) THEN
		IF INSTR(needle$, "[") THEN
		    expr = REGEX(txt$, CONCAT$(" ", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[|,", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[" ))
		ELSE
		    expr = REGEX(txt$, CONCAT$(" ", needle$, ",| ", needle$, ";|\\*", needle$, " |,", needle$, ",|,", needle$, ";| ", needle$, " +="))
		END IF
		IF ISTRUE(expr) THEN BREAK
	    ENDIF
        ENDIF
    WEND

    CLOSE FILE thefile

    RETURN expr

END FUNCTION

'----------------------------------------------------------------------------------------------

FUNCTION Check_Type$(STRING filename$, STRING v$, NUMBER position)

    LOCAL txt$, needle$
    LOCAL expr
    LOCAL thefile TYPE FILE*

    needle$ = CHOP$(REPLACE$(v$, "*", "\\*"))

    OPEN filename$ FOR READING AS thefile

    SEEK thefile OFFSET position

    WHILE NOT(ENDFILE(thefile)) DO

        READLN txt$ FROM thefile
        IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
            expr = REGEX(txt$, "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING")
	    IF ISTRUE(expr) THEN
		IF INSTR(needle$, "[") THEN
		    IF INSTR(needle$, g_STRINGSIGN$) THEN
			expr = REGEX(txt$, CONCAT$(" *", LEFT$(needle$, INSTR(needle$, "[")-1), "\\["))
		    ELSE
			expr = REGEX(txt$, CONCAT$(" ", LEFT$(needle$, INSTR(needle$, "[")-1), "\\["))
		    ENDIF
		ELSE
		    expr = REGEX(txt$, CONCAT$(" ", needle$, ",| ", needle$, ";|,", needle$, ",|,", needle$, ";| ", needle$, " +="))
		END IF
		IF ISTRUE(expr) THEN BREAK
	    ENDIF
        ENDIF
    WEND

    CLOSE FILE thefile

    IF ISTRUE(expr) THEN RETURN txt$

    RETURN ""

END FUNCTION

'----------------------------------------------------------------------------------------------

FUNCTION Search(STRING file$, STRING line$, NUMBER position)

    LOCAL found
    LOCAL txt$
    LOCAL handle TYPE FILE*

    found = -1

    OPEN file$ FOR READING AS handle

    SEEK handle OFFSET position

    WHILE NOT(ENDFILE(handle)) DO
        READLN txt$ FROM handle
	IF INSTR(txt$, line$) THEN
	    found = TRUE
	    BREAK
	ENDIF
    WEND
    CLOSE FILE handle

    RETURN found

END FUNCTION

'----------------------------------------------------------------------------------------------

SUB Print_Element (STRING arg$)

    LOCAL len, check

    ' Get part just before '('
    len = INSTR(arg$, "(")-1
    IF len < 0 THEN len = LEN(arg$)

    ' Check on string by reference variable
    check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
    IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
    ENDIF

    ' Check if var is string var
    IF INSTR(MID$(arg$, 1, len), g_STRINGSIGN$) OR INSTR(MID$(arg$, 1, len), CHR$(34)) OR REGEX(MID$(arg$, 1, len), "gettext|ngettext") OR check >= 0 THEN
	WRITELN "__b2c__assign = ", arg$, "; if(__b2c__assign != NULL) fprintf(stdout, \"%s\", __b2c__assign);" TO g_CFILE
    ELSE
	WRITELN "fprintf(stdout, \"%s\", STR", g_STRINGSIGN$, "(", arg$, "));" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Print(STRING arg$)

    LOCAL exp$, form$
    LOCAL x, in_string, in_func, pos, escaped

    ' Check if argument
    IF ISTRUE(LEN(arg$)) THEN

	' Omit semicolon if there is one
	IF EQUAL(RIGHT$(arg$, 1), ";") THEN
	    exp$ = LEFT$(arg$, LEN(arg$) - 1)
	ELSE
	    exp$ = arg$
	END IF

	' If there is a FORMAT argument
	IF INSTR(exp$, " FORMAT ") THEN
	    form$ = MID$(exp$, INSTR(exp$, " FORMAT ") + 8)
	    WRITELN "fprintf(stdout, ", form$, ", ", LEFT$(exp$, INSTR(exp$, " FORMAT ")), ");" TO g_CFILE
	ELSE
	    ' Start miniparser
	    in_string = FALSE
	    in_func = 0
	    pos = 1
	    escaped = 0

	    FOR x = 1 TO LEN(exp$)
		IF EQUAL(MID$(exp$, x, 1), ",") THEN
		    IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
			Print_Element(CHOP$(MID$(exp$, pos, x-pos)))
			pos = x + 1
			escaped = FALSE
		    END IF
		ELIF EQUAL(MID$(exp$, x, 1), "\\") THEN
		    escaped = TRUE
		ELIF EQUAL(MID$(exp$, x, 1), CHR$(34)) THEN
		    IF ISFALSE(escaped) THEN
			in_string = NOT(in_string)
		    END IF
		    escaped = FALSE
		ELIF EQUAL(MID$(exp$, x, 1), "(") THEN
		    IF ISFALSE(in_string) THEN
			INCR in_func
		    END IF
		    escaped = FALSE
		ELIF EQUAL(MID$(exp$, x, 1), ")") THEN
		    IF ISFALSE(in_string) THEN
			DECR in_func
		    END IF
		    escaped = FALSE
		ELSE
		    escaped = FALSE
		ENDIF
	    NEXT
	    Print_Element(CHOP$(MID$(exp$, pos)))

	    ' If line ends with ';' then skip newline
	    IF ISFALSE(EQUAL(RIGHT$(arg$, 1), ";")) THEN
		WRITELN "fprintf(stdout, \"\\n\");" TO g_CFILE
	    END IF
	END IF

    ELSE
	WRITELN "fprintf(stdout, \"\\n\");" TO g_CFILE
    END IF

    ' Flush print buffer
    WRITELN "fflush(stdout);" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Input(STRING arg$)

    LOCAL x, in_string, in_func, pos, check, escaped
    LOCAL type$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(arg$)) THEN
	PRINT NL$, "ERROR: empty INPUT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Start miniparser
    in_string = FALSE
    in_func = 0
    pos = 1
    escaped = 0

    FOR x = 1 TO LEN(arg$)
	IF ISTRUE(EQUAL(MID$(arg$, x, 1), ",")) THEN
	    IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
		Print_Element(CHOP$(MID$(arg$, pos, x-pos)))
		pos = x+1
		escaped = FALSE
	    END IF
	ELIF EQUAL(MID$(arg$, x, 1), "\\") THEN
	    escaped = TRUE
	ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), CHR$(34))) THEN
	    IF ISFALSE(escaped) THEN
		in_string = NOT(in_string)
	    END IF
	    escaped = FALSE
	ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), "(")) THEN
	    IF ISFALSE(in_string) THEN
		INCR in_func
	    END IF
	    escaped = FALSE
	ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), ")")) THEN
	    IF ISFALSE(in_string) THEN
		DECR in_func
	    END IF
	    escaped = FALSE
	ELSE
	    escaped = FALSE
	ENDIF
    NEXT
    arg$ = CHOP$(MID$(arg$, pos))

    ' Check type of var, string?
    IF INSTR(arg$, g_STRINGSIGN$) THEN

	IF NOT(REGEX(arg$, "\\[.*\\]")) THEN
	    ' Is variable declared already?
	    check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
	    IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
		check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
	    ENDIF
	    IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE
	END IF

	' Translate function to C function
	WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE
	WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE

	' Make sure internal var is copied to var of program
	WRITELN arg$, " = (char*)realloc(", arg$, ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE
	WRITELN "if(__b2c__counter == 1) strncpy(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE
	WRITELN "else strncat(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE
	WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE
	' Cut off last newline
	WRITELN "if (strlen(__b2c__input__buffer))", arg$, "[strlen(", arg$, ")-1] = '\\0';" TO g_CFILE
    ' Var is numeric or stringarray
    ELSE
	' Variable may not be array, these should be defined with DECLARE
	IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN

	    ' Is variable declared already?
	    check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	    IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0)

	    IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE
	END IF

	' Get the type
	type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
	    type$ = Check_Type$(g_CFILE$, arg$, 0)
	END IF

	' Translate function to C function - we do not need endless buffer here because numbers never can have more than 10 digits anyway
	WRITELN "memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, "); __b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE

	' Make sure internal var is copied to var of program
	IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN
	    WRITELN arg$, " = atof(__b2c__input__buffer);" TO g_CFILE
	ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
	    WRITELN arg$, " = atol(__b2c__input__buffer);" TO g_CFILE
	ELSE
	    WRITELN arg$, " = atoi(__b2c__input__buffer);" TO g_CFILE
	END IF
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_For(STRING arg$)

    LOCAL var$, tmp$, from$, to$, step$
    LOCAL check

    ' Get the variablename without (surrounding) spaces
    var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1))
    tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1))

    ' Do we have a STRING var?
    IF INSTR(var$, g_STRINGSIGN$) THEN
	PRINT NL$, "ERROR: variable in FOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' cannot be string!"
	END 1
    END IF

    ' Check if TO is available
    IF NOT(INSTR(tmp$, " TO ")) THEN
	PRINT NL$, "ERROR: missing TO in FOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the starting and ending value
    from$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " TO ") - 1))
    to$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TO ") + 3))

    ' Check if there is a STEP
    IF ISTRUE(INSTR(to$, " STEP ")) THEN
	step$ = CHOP$(MID$(to$, INSTR(to$, " STEP ") + 5))
	to$ = CHOP$(LEFT$(to$, INSTR(to$, " STEP ") - 1))
    ELSE
	step$ = "1"
    END IF

    ' Variable may not be array, these should be defined with DECLARE
    IF NOT(REGEX(var$, "\\[.*\\]")) AND ISFALSE(INSTR(var$, ".")) THEN

	' Is variable declared already?
	check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)

	IF ISFALSE(check) THEN WRITELN "long ", var$, ";" TO g_HFILE
    END IF

    ' Translate function to C function
    IF VAL(step$) < 0 THEN
	WRITELN "for(", var$," = ", from$, "; ", var$, " >= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE
    ELSE
	WRITELN "for(", var$," = ", from$, "; ", var$, " <= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_While (STRING arg$)

    ' Check if DO is available
    IF ISFALSE(INSTRREV(arg$, " DO")) THEN
	WRITELN "while(", Parse_Equation$(arg$), "){" TO g_CFILE
    ELSE
	WRITELN "while(", Parse_Equation$(LEFT$(arg$, INSTRREV(arg$, " DO"))), "){" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------
' $1: name of ASSOC variable
' $2: name of index
' $3: actual value to assign
' $4: recursion level

SUB Relate_Recurse(STRING var$, STRING str$, STRING tmp$, NUMBER lvl)

    LOCAL rel$
    LOCAL ctr

    ' Check endless recursion
    INCR lvl
    IF lvl > g_RELATE_CTR THEN
	PRINT NL$, "ERROR: Endless recursion in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Now add relation
    FOR ctr = 0 TO g_RELATE_CTR
	IF EQUAL(LEFT$(g_RELATE$[ctr], LEN(var$)), var$) THEN
	    rel$ = MID$(g_RELATE$[ctr], INSTR(g_RELATE$[ctr], " ")+1)
	    WRITELN "if(__b2c__", rel$, "_exist (", str$, " == NULL) __b2c__", rel$, "__add(", str$, ";" TO g_CFILE
	    IF INSTR(rel$, g_STRINGSIGN$) THEN
		WRITELN "__b2c__", rel$, "_exist(", str$, "->value = realloc(__b2c__", rel$, "_exist(", str$, "->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE
		WRITELN "strcpy(__b2c__", rel$, "_exist(", str$, "->value, ", tmp$, ");" TO g_CFILE
	    ELSE
		WRITELN "__b2c__", rel$, "_exist(", str$, "->value = ", tmp$, ";" TO g_CFILE
	    END IF
	    Relate_Recurse(rel$, str$, tmp$, lvl)
	END IF
    NEXT

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Let(STRING arg$)

    LOCAL check, ctr
    LOCAL var$, tmp$, str$, lft$, rel$, ptr$

    ' Check if we have an argument at all
    IF NOT(INSTR(arg$, "=")) THEN
	PRINT NL$, "ERROR: could not parse line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename without surrounding spaces
    var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1))
    tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1))

    ' Check if var is string var, exclude RECORD elements
    IF REGEX(var$, CONCAT$(g_STRINGSIGN$, "$")) AND NOT(INSTR(var$, ".")) THEN
	' Is variable declared already?
	check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", var$, " = NULL;"), 0)
	ENDIF

	IF check < 0 AND NOT(REGEX(g_PROTOTYPE$, CONCAT$(".* ", var$, "[ ,)]+"))) THEN
	    WRITELN "char *", var$, " = NULL;" TO g_HFILE
	END IF

    ' Assume number, exclude RECORD elements
    ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND NOT(EQUAL(var$, "ERROR")) AND NOT(REGEX(var$, "\\(.*\\)")) THEN

	' Is variable declared already?
	check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)

	IF ISFALSE(check) AND NOT(REGEX(g_PROTOTYPE$, CONCAT$(".* ", var$, "[ ,)]+"))) THEN
	    IF INSTR(tmp$, ".") AND NOT(INSTR(tmp$, CHR$(34))) THEN WRITELN "double ", var$, ";" TO g_HFILE
	    ELSE WRITELN "long ", var$, ";" TO g_HFILE
	END IF
    END IF

    ' Check if there is associative array assignment
    IF REGEX(var$, "\\(.*\\)$") THEN
	lft$ = LEFT$(var$, INSTR(var$, "(") - 1)
	str$ = MID$(var$, INSTR(var$, "(") + 1)
	WRITELN "if(__b2c__", lft$, "_exist (", str$, " == NULL) __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
	IF INSTR(lft$, g_STRINGSIGN$) THEN
	    WRITELN "__b2c__", lft$, "_exist(", str$, "->value = realloc(__b2c__", lft$, "_exist(", str$, "->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE
	    WRITELN "strcpy(__b2c__", lft$, "_exist(", str$, "->value, ", tmp$, ");" TO g_CFILE
	ELSE
	    WRITELN "__b2c__", lft$, "_exist(", str$, "->value = ", tmp$, ";" TO g_CFILE
	END IF
	' Check for relations
	Relate_Recurse(lft$, str$, tmp$, -1)

    ' Do we have a STRING variable not STRING array?
    ELIF INSTR(var$, g_STRINGSIGN$) AND NOT(REGEX(var$, CONCAT$(".*\\[.*", g_STRINGSIGN$, ".*\\].*"))) THEN
	WRITELN "__b2c__assign = (char*) strdup (", tmp$, "); ", g_WITHVAR$, var$, " = (char*)realloc(", g_WITHVAR$, var$, ", (strlen(__b2c__assign)+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(", g_WITHVAR$, var$, ", __b2c__assign); free(__b2c__assign);" TO g_CFILE
	' Also check if string var already is used for IMPORT, if so, perform dlopen again
	ptr$ = REPLACE$(REPLACE$(var$, CHR$(34), ""), "-", "")
	ptr$ = REPLACE$(REPLACE$(REPLACE$(ptr$, ".", ""), "/", ""), "_", "")
	check = Search(g_CFILE$, CONCAT$("void* __b2c__dlopen__pointer_", ptr$, ";"), 0)
	IF check >= 0 THEN
	    WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", var$, ", RTLD_LAZY);" TO g_CFILE
	END IF

    ELSE
	WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Open(STRING arg$)

    LOCAL check
    LOCAL file$, tmp$, mode$, handle$

    ' Check if FOR is available
    IF NOT(INSTR(arg$, " FOR ")) THEN
	PRINT NL$, "ERROR: missing FOR in OPEN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if AS is available
    IF NOT(INSTR(arg$, " AS ")) THEN
	PRINT NL$, "ERROR: missing AS in OPEN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the file, mode and handle
    file$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FOR ") - 1))
    tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FOR ") + 5))

    mode$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " AS ") - 1))
    handle$ = CHOP$(MID$(tmp$, INSTR(tmp$, " AS ") + 4))

    ' Check if var is string var
    IF INSTR(handle$, g_STRINGSIGN$) AND NOT(EQUAL(mode$, "MEMORY")) THEN
	PRINT NL$, "ERROR: variable for OPEN at line ", g_COUNTER, " in file '", g_CURFILE$, "' cannot be string!"
	END 1
    END IF

    ' Check if variable was declared
    IF NOT(INSTR(handle$, ".")) THEN
	check = Check_Declared(g_HFILE$, handle$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, handle$, 0)
    END IF

    ' File or dir?
    IF EQUAL(mode$, "DIRECTORY") THEN
	IF ISFALSE(check) THEN
	    WRITELN "DIR* ", handle$, ";" TO g_HFILE
	END IF
    ELIF EQUAL(mode$, "MEMORY") THEN
	IF ISFALSE(check) THEN
	    WRITELN "char* ", handle$, ";" TO g_HFILE
	END IF
	check = Check_Declared(g_HFILE$, CONCAT$("__b2c_mem_", handle$, ";"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, CONCAT$("__b2c_mem_", handle$, ";"), 0)
	IF ISFALSE(check) THEN
	    WRITELN "long __b2c_mem_", handle$, ";" TO g_HFILE
	END IF
    ELIF EQUAL(mode$, "NETWORK") OR EQUAL(mode$, "SERVER") THEN
	IF ISFALSE(check) THEN
	    WRITELN "int ", handle$, ";" TO g_HFILE
	END IF
    ELSE
	IF ISFALSE(check) THEN
	    WRITELN "FILE* ", handle$, ";" TO g_HFILE
	END IF
    END IF

    ' Convert to C syntax
    IF EQUAL(mode$, "READING") THEN
	WRITELN handle$, " = fopen(", file$, ", \"r\");" TO g_CFILE
	WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "WRITING") THEN
	WRITELN handle$, " = fopen(", file$, ", \"w\");" TO g_CFILE
	WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "APPENDING") THEN
	WRITELN handle$, " = fopen(", file$, ", \"a\");" TO g_CFILE
	WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "READWRITE") THEN
	WRITELN handle$, " = fopen(", file$, ", \"r+\");" TO g_CFILE
	WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "DIRECTORY") THEN
	WRITELN handle$, " = opendir(", file$, ");" TO g_CFILE
	WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "MEMORY") THEN
	WRITELN handle$, " = (char*)", file$, "; __b2c_mem_", handle$, " = ", file$, ";" TO g_CFILE
	WRITELN "if(!__b2c__trap){__b2c__memory__check(", handle$, "); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "NETWORK") THEN
	' Network code
	WRITELN "if (strstr(", file$, ", \":\") == NULL){ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\\n\", ERR", g_STRINGSIGN$, "(ERROR), ", file$, "); exit(ERROR);}" TO g_CFILE
	WRITELN "strncpy(__b2c__data_client, ", file$, ", ", g_BUFFER_SIZE, ");__b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");__b2c__he = gethostbyname(__b2c__host);" TO g_CFILE
	WRITELN "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN handle$, " = socket(PF_INET, SOCK_STREAM, 0);" TO g_CFILE
	WRITELN "if (", handle$, " == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN "__b2c__to.tv_sec = ", g_OPTION_SOCKET, "; __b2c__to.tv_usec = 0; setsockopt(", handle$, ", SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" TO g_CFILE
	WRITELN "setsockopt(", handle$, ", SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int)); __b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
	WRITELN "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\\0', sizeof(__b2c__addr.sin_zero));" TO g_CFILE
	WRITELN "__b2c__result = connect(", handle$, ", (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE
	WRITELN "if(__b2c__result == -1) {if(!__b2c__trap){ERROR = 13;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELIF EQUAL(mode$, "SERVER") THEN
	' Network code
	WRITELN "if (strstr(", file$, ", \":\") == NULL){ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\\n\", ERR", g_STRINGSIGN$, "(ERROR), ", file$, "); exit(ERROR);}" TO g_CFILE
	WRITELN "if(strcmp(__b2c__data_server, ", file$, ")) {strncpy(__b2c__data_server, ", file$, ", ", g_BUFFER_SIZE, ");__b2c__host = strtok(__b2c__data_server, \":\"); __b2c__port = strtok(NULL, \":\");__b2c__he = gethostbyname(__b2c__host);" TO g_CFILE
	WRITELN "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN "__b2c__handle = socket(AF_INET, SOCK_STREAM, 0);" TO g_CFILE
	WRITELN "if (__b2c__handle == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN "__b2c__to.tv_sec = ", g_OPTION_SOCKET, "; __b2c__to.tv_usec = 0; setsockopt(__b2c__handle, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" TO g_CFILE
	WRITELN "setsockopt(__b2c__handle, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int));__b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
	WRITELN "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);memset(&(__b2c__addr.sin_zero), '\\0', sizeof(__b2c__addr.sin_zero));" TO g_CFILE
	WRITELN "__b2c__result = bind(__b2c__handle, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE
	WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 17;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN "__b2c__result = listen(__b2c__handle, ", g_MAX_BACKLOG, ");" TO g_CFILE
	WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 18;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN "strncpy(__b2c__data_server, ", file$, ", ", g_BUFFER_SIZE, "); /* Restore data because of strtok */} __b2c__result = accept(__b2c__handle, NULL, 0);" TO g_CFILE
	WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
	WRITELN handle$, "= __b2c__result;" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Seek(STRING arg$)

    LOCAL dim

    ' Check if we have an argument at all
    IF ISFALSE(LEN(arg$)) THEN
	PRINT NL$, "ERROR: empty SEEK at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if OFFSET is available
    IF NOT(INSTR(arg$, " OFFSET ")) THEN
	PRINT NL$, "ERROR: missing OFFSET in SEEK statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    SPLIT arg$ BY " " TO element$ SIZE dim

    ' Convert to C function
    IF dim EQ 3 THEN
	WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE
    ELIF dim EQ 5 THEN
	IF EQUAL(element$[5], "START") THEN
	    WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE
	ELIF EQUAL(element$[4], "CURRENT") THEN
	    WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_CUR);" TO g_CFILE
	ELIF EQUAL(element$[4], "END") THEN
	    WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_END);" TO g_CFILE
	END IF
    ELSE
	PRINT NL$, "ERROR: erroneous SEEK statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Copy(STRING arg$)

    LOCAL from$, to$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(arg$)) THEN
	PRINT NL$, "ERROR: empty COPY at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in COPY statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the filename and copyname
    from$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1))
    to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))

    ' Translate to C function
    WRITELN "__b2c__inFile = fopen(", from$, ", \"r\"); __b2c__outFile = fopen(", to$, ", \"w\"); __b2c__Byte = 0;" TO g_CFILE
    WRITELN "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" TO g_CFILE
    WRITELN "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" TO g_CFILE
    WRITELN "fputc(__b2c__Byte,__b2c__outFile); }}" TO g_CFILE
    WRITELN "fclose(__b2c__inFile); fclose(__b2c__outFile);}" TO g_CFILE
    WRITELN "else { if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Rename(STRING arg$)

    LOCAL from$, to$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(arg$)) THEN
	PRINT NL$, "ERROR: empty RENAME at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in RENAME statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the filename and copyname
    from$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1))
    to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))

    ' Translate to C function
    WRITELN "if(rename(", from$, ", ", to$, ") < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Readln(STRING arg$)

    LOCAL dim, check

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " FROM ")) THEN
	PRINT NL$, "ERROR: missing FROM in READLN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    SPLIT arg$ BY " " TO element$ SIZE dim

    ' Check if var is string var
    IF NOT(INSTR(element$[1], g_STRINGSIGN$)) THEN
	PRINT NL$, "ERROR: variable for READLN at line ", g_COUNTER, " in file '", g_CURFILE$, "' must be string!"
	END 1
    END IF

    ' Check if var is string var, exclude RECORD elements
    IF NOT(REGEX(element$[1], "\\[.*\\]")) THEN
	' Is variable declared already?
	check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
	ENDIF

	IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
    END IF

    ' Translate function to C function
    WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE
    WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", ", element$[3], ");" TO g_CFILE

    ' Make sure internal var is copied to var of program
    WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE
    WRITELN "if(__b2c__counter == 1) strncpy(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE
    WRITELN "else strncat(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE
    WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE
    ' Cut off last newline
    WRITELN "if (strlen(__b2c__input__buffer))", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE
    ' Cut off CR if available
    WRITELN "if(strlen(", element$[1], ")>0 && ", element$[1], "[strlen(", element$[1], ")-1]=='\\r') ", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Writeln(STRING arg$)

    LOCAL in_string, in_func, pos, escaped, x, len
    LOCAL var$, to$

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: missing TO in WRITELN statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    var$ = LEFT$(arg$, INSTRREV(arg$, " TO "))
    to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4))

    ' Start miniparser
    in_string = FALSE
    in_func = 0
    pos = 1
    escaped = 0

    FOR x = 1 TO LEN(var$)
	IF ISTRUE(EQUAL(MID$(var$, x, 1), ",")) THEN
	    IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
		len = INSTR(MID$(var$, pos, x-pos), "(")-1
		IF len < 0 THEN len = x-pos
		IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN
		    WRITELN "fprintf(", to$, ", \"%s\", ", MID$(var$, pos, x-pos), ");" TO g_CFILE
		ELSE
		    WRITELN "fprintf(", to$, ", \"%s\", STR", g_STRINGSIGN$, "(", MID$(var$, pos, x-pos), "));" TO g_CFILE
		END IF
		pos = x+1
		escaped = FALSE
	    END IF
	ELIF EQUAL(MID$(var$, x, 1), "\\") THEN
	    escaped = TRUE
	ELIF ISTRUE(EQUAL(MID$(var$, x, 1), CHR$(34))) THEN
	    IF ISFALSE(escaped) THEN
		in_string = NOT(in_string)
	    END IF
	    escaped = FALSE
	ELIF ISTRUE(EQUAL(MID$(var$, x, 1), "(")) THEN
	    IF ISFALSE(in_string) THEN
		INCR in_func
	    END IF
	    escaped = FALSE
	ELIF ISTRUE(EQUAL(MID$(var$, x, 1), ")")) THEN
	    IF ISFALSE(in_string) THEN
		DECR in_func
	    END IF
	    escaped = FALSE
	ELSE
	    escaped = FALSE
	ENDIF
    NEXT
    var$ = MID$(var$, pos)

    ' Write last element to file
    len = INSTR(var$, "(")-1
    IF len < 0 THEN len = LEN(var$)
    IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN
	WRITELN "fprintf(", to$, ", \"%s\\n\", ", var$, ");" TO g_CFILE
    ELSE
	WRITELN "fprintf(", to$, ", \"%s\\n\", STR", g_STRINGSIGN$, "(", var$, "));" TO g_CFILE
    END IF
    WRITELN "fflush(", to$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Getbyte(STRING arg$)

    LOCAL dim, check
    LOCAL var$, to$, size$

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " FROM ")) THEN
	PRINT NL$, "ERROR: missing FROM in GETBYTE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    var$ = CHOP$(LEFT$(arg$, INSTRREV(arg$, " FROM ")))
    to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " FROM ") + 6))

    ' Check if SIZE is available
    IF INSTR(to$, " SIZE ") THEN
	size$ = MID$(to$, INSTR(to$, " SIZE ") + 6)
	to$ = MID$(to$, 1, INSTR(to$, " SIZE "))
    ELSE
	size$ = "1"
    END IF

    ' Declare variable if not done yet, assuming long
    IF NOT(INSTR(var$, ".")) THEN
	check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)

	IF ISFALSE(check) THEN WRITELN "long ", var$, ";" TO g_HFILE
    END IF

    ' Translate function to C function
    WRITELN "if(!__b2c__trap){__b2c__memory__check((char *)", var$, "); if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    WRITELN "__b2c__counter = fread((void*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", size$, ", ", to$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Putbyte(STRING arg$)

    LOCAL dim
    LOCAL var$, to$, size$

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: missing TO in PUTBYTE statement at line at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    var$ = LEFT$(arg$, INSTRREV(arg$, " TO "))
    to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4))

    ' Check if SIZE is available
    IF INSTR(to$, " SIZE ") THEN
	size$ = MID$(to$, INSTR(to$, " SIZE ") + 6)
	to$ = MID$(to$, 1, INSTR(to$, " SIZE "))
    ELSE
	size$ = "1"
    END IF

    ' Translate function to C function
    WRITELN "if(!__b2c__trap){__b2c__memory__check((char *)", var$, "); if(ERROR){if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    WRITELN "__b2c__counter = fwrite((void*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", size$, ", ", to$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Getfile(STRING arg$)

    LOCAL dim, check

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " FROM ")) THEN
	PRINT NL$, "ERROR: missing FROM in GETFILE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    SPLIT arg$ BY " " TO element$ SIZE dim

    ' Translate function to C function
    WRITELN "__b2c__dir = readdir(", element$[3], ");" TO g_CFILE

    ' Check if variable is declared
    IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN
	check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
	ENDIF
    END IF

    IF check < 0 AND NOT(REGEX(element$[1], "\\[.*\\]")) AND NOT(INSTR(element$[1], ".")) THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE

    ' Always realloc VAR to correct size, maybe it was resized somewhere else
    WRITELN "if(__b2c__dir != NULL) {", element$[1], " = realloc(", element$[1], ", (strlen(__b2c__dir->d_name)+1)*sizeof(char));" TO g_CFILE
    ' Make sure internal var is copied to var of program
    WRITELN "strcpy(", element$[1], ", __b2c__dir->d_name); ", element$[1], "[strlen(__b2c__dir->d_name)] = '\\0';}" TO g_CFILE
    WRITELN "else {", element$[1], " = realloc(", element$[1], ", sizeof(char)); ", element$[1], "[0] = '\\0';}" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Receive(STRING arg$)

    LOCAL dim, check
    LOCAL size$, chunk$

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " FROM ")) THEN
	PRINT NL$, "ERROR: Missing FROM in RECEIVE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get filedescriptor
    SPLIT CHOP$(arg$) BY " " TO element$ SIZE dim

    ' Check for optional chunksize
    SELECT dim
	CASE 5
	    chunk$ = element$[5]
	    size$ = ""
	CASE 7
	    chunk$ = element$[5]
	    size$ = element$[7]
	DEFAULT
	    chunk$ = STR$(g_BUFFER_SIZE)
	    size$ = ""
    END SELECT

    ' Variable may not be array, these should be defined with DECLARE
    IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN
	check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0)

	IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE
    END IF

    ' Check if variable is declared
    IF INSTR(element$[1], g_STRINGSIGN$) THEN
	check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
	ENDIF

	IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
	WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", chunk$, "+1)*sizeof(char)); memset(", element$[1], ", '\\0', sizeof(char)*(", chunk$, "+1));" TO g_CFILE
    END IF

    ' Translate function to C function
    IF LEN(size$) EQ 0 THEN
	WRITELN "if(recv(", element$[3], ", (void*)", element$[1], ", ", chunk$, ", 0) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    ELSE
	WRITELN "if((", size$, " = recv(", element$[3], ", (void*)", element$[1], ", ", chunk$,", 0)) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Send(STRING arg$)

    LOCAL to$, var$, chunk$

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in SEND statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename without surrounding spaces
    var$ = LEFT$(arg$, INSTR(arg$, " TO "))

    ' Get filedescriptor
    to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))

    IF INSTR(to$, " CHUNK ") THEN
	chunk$ = MID$(to$, INSTR(to$, " CHUNK ") + 7)
	to$ = MID$(to$, 1, INSTR(to$, " CHUNK ") - 1)
    ELSE
	chunk$ = CONCAT$("strlen(", var$, ")")
    END IF

    ' Translate function to C function
    WRITELN "if(send(", to$, ", (void*)", var$, ", ", chunk$, ", 0) < 0) {if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Getline(STRING arg$)

    LOCAL dim, check

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " FROM ")) THEN
	PRINT NL$, "ERROR: missing FROM in GETLINE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    SPLIT arg$ BY " " TO element$ SIZE dim

    ' Check if var is string var
    IF NOT(INSTR(element$[1], g_STRINGSIGN$)) THEN
	PRINT NL$, "ERROR: variable for GETLINE at line $g_COUNTER in file ", g_COUNTER, " in file '", g_CURFILE$, "' must be string!"
	END 1
    END IF

    ' Check if variable is declared
    IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN
	' Is variable declared already?
	check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
	ENDIF

	IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
    END IF

    ' Translate function to C function
    WRITELN "if (", element$[3], " == NULL ||", CONCAT$("*", element$[3]) , " == '\\0') {", element$[1], " = (char*)realloc(", element$[1], ", 2*sizeof(char)); strcpy(", element$[1], ", \"\");}" TO g_CFILE
    WRITELN "else { __b2c__assign = ", element$[3], "; while(*", element$[3], " != '\\0' && *", element$[3], " != '\\n') ", element$[3], "++;" TO g_CFILE

    ' Make sure internal var is copied to var of program
    WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", element$[3], "-__b2c__assign+1)*sizeof(char));" TO g_CFILE
    WRITELN "strncpy(", element$[1], ", __b2c__assign, ", element$[3], "-__b2c__assign);" TO g_CFILE

    ' Make sure to end the string
    WRITELN element$[1], "[(", element$[3], "-__b2c__assign)] = '\\0'; ", element$[3], "++;}" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Putline(STRING arg$)

    LOCAL in_string, in_func, pos, escaped, x, len
    LOCAL var$, to$

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: missing TO in PUTLINE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the variablename, filedescriptor
    var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ")))
    to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))

    ' Start miniparser
    in_string = FALSE
    in_func = 0
    pos = 1
    escaped = 0

    FOR x = 1 TO LEN(var$)
	IF ISTRUE(EQUAL(MID$(var$, x, 1), ",")) THEN
	    IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
		len = INSTR(MID$(var$, pos, x-pos), "(")-1
		IF len < 0 THEN len = x-pos
		IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN
		    WRITELN "strcat(", to$, ", ", CHOP$(MID$(var$, pos, x-pos)), ");", to$, "+=strlen(", CHOP$(MID$(var$, pos, x-pos)), ");" TO g_CFILE
		ELSE
		    WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));", to$, "+=strlen(STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));" TO g_CFILE
		END IF
		pos = x+1
		escaped = FALSE
	    END IF
	ELIF EQUAL(MID$(var$, x, 1), "\\") THEN
	    escaped = TRUE
	ELIF ISTRUE(EQUAL(MID$(var$, x, 1), CHR$(34))) THEN
	    IF ISFALSE(escaped) THEN
		in_string = NOT(in_string)
	    END IF
	    escaped = FALSE
	ELIF ISTRUE(EQUAL(MID$(var$, x, 1), "(")) THEN
	    IF ISFALSE(in_string) THEN
		INCR in_func
	    END IF
	    escaped = FALSE
	ELIF ISTRUE(EQUAL(MID$(var$, x, 1), ")")) THEN
	    IF ISFALSE(in_string) THEN
		DECR in_func
	    END IF
	    escaped = FALSE
	ELSE
	    escaped = FALSE
	ENDIF
    NEXT
    var$ = MID$(var$, pos)

    ' Check if var is string var
    len = INSTR(MID$(var$, pos, x-pos), "(")-1
    IF len < 0 THEN len = x-pos
    IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN
	WRITELN "strcat(", to$, ", ", var$, "); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(", var$, ")+1;" TO g_CFILE
    ELSE
	WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", var$, ")); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(STR", g_STRINGSIGN$, "(", var$, "))+1;" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_SubFunc(STRING arg$)

    LOCAL x, dim, check
    LOCAL arg_s$, dim$, arr$, size$

    ' Check argument
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty SUB/FUNCTION at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if we are in a sub already
    IF LEN(g_FUNCNAME$) > 0 THEN
	PRINT NL$, "ERROR: cannot define a SUB/FUNCTION within a SUB/FUNCTION at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the funcname
    IF INSTR(arg$, "(") THEN
	g_ORIGFUNCNAME$ = CHOP$(LEFT$(arg$, INSTR(arg$, "(")))
	g_PROTOTYPE$ = CHOP$(LEFT$(arg$, INSTR(arg$, "(")))
    ELSE
	g_ORIGFUNCNAME$ = CHOP$(CONCAT$(arg$, "("))
	g_PROTOTYPE$ = CHOP$(CONCAT$(arg$, "("))
    END IF

    ' Start miniparser to duplicate string arguments
    arg_s$ = CHOP$(MID$(arg$, INSTR(arg$, "(") + 1))

    SPLIT arg_s$ BY "," TO element$ SIZE dim

    x = 1
    WHILE dim > 1 DO
	IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN
	    element$[x] = CHOP$(element$[x])
            arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1)
            dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
            IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],")
	        g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char** ", arr$, " = __b2c_", arr$, ";")
		g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
            ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = __b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ";")
		g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
	    ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],")
		IF LEN(dim$) < 1 THEN
		    PRINT NL$, "ERROR: cannot pass string array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"] = { NULL };")
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){if(__b2c_", arr$, "[__b2c__ctr]!=NULL) ", arr$, "[__b2c__ctr] = strdup(__b2c_", arr$, "[__b2c__ctr]);}")
	        g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);}")
		g_PROTOTYPE$=CONCAT$(g_PROTOTYPE$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",")
	    ELSE
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = strdup(__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ");")
		g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(MID$(element$[x], INSTR(element$[x], " "))))
		g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
	    END IF
	ELSE
	    element$[x] = CHOP$(element$[x])
	    IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN
		PRINT NL$, "ERROR: cannot pass multidimensional numeric array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	    ELIF REGEX(element$[x], ".*\\[\\].*") THEN
		g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ","))
	    ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
		dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
		IF LEN(dim$) < 1 THEN
		    PRINT NL$, "ERROR: cannot pass numeric array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
		arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1)
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, MID$(element$[x], 1, INSTR(element$[x], " "))," __b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],")
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, MID$(element$[x], 1, INSTR(element$[x], " ")), " ", arr$, "[", dim$, "+", STR$(g_OPTION_BASE), "] = { 0 };")
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){", arr$, "[__b2c__ctr] = __b2c_", arr$, "[__b2c__ctr];}")
	    ELIF INSTR(element$[x], "VAR ") THEN
	        PRINT NL$, "ERROR: variable argument list cannot be followed by other arguments at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	    ELSE
		g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ","))
	    END IF
	    g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", CHOP$(element$[x]), ",")
	END IF
	INCR x
	DECR dim
    WEND

    ' Last token in the sequence of arguments
    IF ISTRUE(dim) THEN
	element$[x] = CHOP$(LEFT$(element$[x], INSTR(element$[x], ")") - 1))
	IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN
	    arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1)
	    dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
            IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])")
	        g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char** ", arr$, " = __b2c_", arr$, ";")
		g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
            ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = __b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ";")
		g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
	    ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])")
		IF LEN(dim$) < 1 THEN
		    PRINT NL$, "ERROR: cannot pass string array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"] = { NULL };")
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){if(__b2c_", arr$, "[__b2c__ctr]!=NULL) ", arr$, "[__b2c__ctr] = strdup(__b2c_", arr$, "[__b2c__ctr]);}")
	        g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);}")
		g_PROTOTYPE$=CONCAT$(g_PROTOTYPE$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")")
	    ELSE
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = strdup(__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ");")
		g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(MID$(element$[x], INSTR(element$[x], " "))))
		g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
	    END IF
	ELSE
	    IF INSTR(g_ORIGFUNCNAME$, element$[x]) OR LEN(element$[x]) EQ 0 THEN element$[x] = "void "
	    IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN
		PRINT NL$, "ERROR: cannot pass multidimensional numeric array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		END 1
	    ELIF REGEX(element$[x], ".*\\[\\].*") THEN
		g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")"))
	    ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
		dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
		IF LEN(dim$) < 1 THEN
		    PRINT NL$, "ERROR: cannot pass numeric array without dimension at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
		arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1)
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, MID$(element$[x], 1, INSTR(element$[x], " "))," __b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])")
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, MID$(element$[x], 1, INSTR(element$[x], " ")), " ", arr$, "[", dim$, "+", STR$(g_OPTION_BASE), "] = { 0 };")
                g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){", arr$, "[__b2c__ctr] = __b2c_", arr$, "[__b2c__ctr];}")
	    ELIF INSTR(element$[x], "VAR ") THEN
		IF INSTR(g_PROTOTYPE$, ",") THEN
		    PRINT NL$, "ERROR: variable argument list cannot be preceded by other arguments at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
		IF NOT(INSTR(element$[x], " SIZE ")) THEN
		    PRINT NL$, "ERROR: variable argument list lacks SIZE argument at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
		arr$ = MID$(element$[x], INSTR(element$[x], " ") + 1):arr$ = CHOP$(LEFT$(arr$, INSTR(arr$, "SIZE ")-1)):size$ = CHOP$(MID$(element$[x], INSTR(element$[x], "SIZE ") + 5))
		IF NOT(INSTR(arr$, g_STRINGSIGN$)) THEN
		    PRINT NL$, "ERROR: variable argument list is not string at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
		    END 1
		END IF
		check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
		IF ISFALSE(check) THEN g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " long ", size$, ";")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "long __b2c__var_", arr$, " = ", STR$(g_OPTION_BASE), "; va_list __b2c__ap; char **", arr$, " = NULL; char* __b2c__va = NULL; ", arr$, " = (char **)realloc(", arr$, ", (__b2c__var_", arr$, "+1) * sizeof(char*));")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "va_start(__b2c__ap, __b2c__name); ", arr$, "[__b2c__var_", arr$, "] = strdup(__b2c__name); while (", arr$, "[__b2c__var_", arr$, "] != NULL) {__b2c__var_", arr$, "++; ", arr$, " = (char **)realloc(", arr$, ", (__b2c__var_", arr$, "+1) * sizeof(char*));")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "__b2c__va = va_arg(__b2c__ap, char*); if(__b2c__va != NULL) ", arr$, "[__b2c__var_", arr$, "] = strdup(__b2c__va); else ", arr$, "[__b2c__var_", arr$, "] = NULL; }")
		g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "va_end(__b2c__ap); ", size$, " = __b2c__var_", arr$, " - ", STR$(g_OPTION_BASE), "; if(__b2c__var_", arr$, " > 0) __b2c__var_", arr$, "--;")
		g_PROTOTYPE$ = CONCAT$("__", g_PROTOTYPE$)
		g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c__name, ...)")
		element$[x] = "char*, ..."
		g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "if(", arr$, " != NULL) {for(__b2c__ctr=", STR$(g_OPTION_BASE), "; __b2c__ctr<=__b2c__var_", arr$, "; __b2c__ctr++) if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);} free(", arr$, ");}")
	    ELSE
		g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")"))
	    END IF
	    g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
	END IF
    END IF

    ' Get original function name
    IF INSTR(g_ORIGFUNCNAME$, " (") THEN
	g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, " (") - 1)
    ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN
	g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, "(") - 1)
    ELSE
	g_FUNCNAME$ = g_ORIGFUNCNAME$
    END IF

    ' Close the current C file
    CLOSE FILE g_CFILE

    ' Add macro in case of VAR argument
    IF INSTR(element$[x], " ...") THEN
	WRITELN "#define ", g_FUNCNAME$, "(...) __", g_FUNCNAME$, "(\"", g_FUNCNAME$, "\", __VA_ARGS__, NULL)" TO g_HFILE
	g_ORIGFUNCNAME$ = CONCAT$("__", g_ORIGFUNCNAME$)
    END IF

    ' Make symbol known to parser
    g_IMPORTED$ = CONCAT$(g_FUNCNAME$, " ", g_IMPORTED$)

    ' Switch to header file
    g_COPY_CFILE$ = g_CFILE$
    g_CFILE$ = CONCAT$(LEFT$(g_CFILE$, INSTR(g_CFILE$, ".c")), g_FUNCNAME$, ".tmp")

    ' Save CATCH routine
    g_ORIGCATCHGOTO$ = g_CATCHGOTO$
    g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"

    ' Open temp C file
    OPEN g_CFILE$ FOR WRITING AS g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Endsub()

    LOCAL tmp_HFILE TYPE FILE*
    LOCAL line$
    LOCAL dim, x

    ' Close the current C file
    CLOSE FILE g_CFILE

    ' Put prototype to header file
    WRITELN "void ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE
    g_PROTOTYPE$ = ""

    ' Open temporary header file
    OPEN CONCAT$(g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") FOR WRITING AS tmp_HFILE

    ' Get original function name
    WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE
    WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COUNTER, " */" TO tmp_HFILE
    IF INSTR(g_ORIGFUNCNAME$, " (") THEN
	WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE
    ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN
	WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE
    ELSE
	WRITELN "void ", g_FUNCNAME$, "(void) {" TO tmp_HFILE
    END IF

    ' Finalize sub
    WRITELN g_STRINGARGS$ TO tmp_HFILE
    OPEN g_CFILE$ FOR READING AS g_CFILE
    WHILE NOT(ENDFILE(g_CFILE)) DO
        READLN line$ FROM g_CFILE
        IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE
    WEND
    CLOSE FILE g_CFILE

    ' Free strings variables if there are any
    SPLIT g_LOCALSTRINGS$ BY " " TO element$ SIZE dim
    FOR x = 1 TO dim
	IF LEN(element$[x]) > 0 THEN WRITELN "if(", element$[x], " != NULL) free(", element$[x], ");" TO tmp_HFILE
    NEXT
    WRITELN g_STRINGARRAYS$ TO tmp_HFILE
    WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE
    WRITELN "}" TO tmp_HFILE

	CLOSE FILE tmp_HFILE
	
    ' Include header file
    IF NOT(INSTR(g_INCLUDE_FILES$, CONCAT$(LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h"))) THEN
	g_INCLUDE_FILES$ = CONCAT$(g_INCLUDE_FILES$, " ", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")
    END IF

    ' Add to total filelist
    g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")

    ' Delete temp funcfile
    DELETE FILE g_CFILE$

    ' Restore mainfile
    g_CFILE$ = g_COPY_CFILE$
    OPEN g_CFILE$ FOR APPENDING AS g_CFILE

    ' Restore CATCH routine
    g_CATCHGOTO$ = g_ORIGCATCHGOTO$

    ' Reset variables
    g_ORIGFUNCNAME$ = ""
    g_FUNCNAME$ = ""
    g_LOCALSTRINGS$ = ""
    g_STRINGARRAYS$ = ""
    g_STRINGARGS$ = ""

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Endfunction()

    IF ISFALSE(LEN(g_FUNCTYPE$)) THEN
	PRINT NL$, "ERROR: function '", g_FUNCNAME$, "' was defined without returning a value or string!"
	END 1
    END IF

    ' Close the current C file
    CLOSE FILE g_CFILE

    ' Put prototype to header file
    WRITELN g_FUNCTYPE$, " ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE
    g_PROTOTYPE$ = ""

    ' Open temporary header file
    OPEN CONCAT$(g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") FOR WRITING AS tmp_HFILE

    ' Get original function name
    WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE
    WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COUNTER, " */" TO tmp_HFILE
    IF NOT(INSTR(g_ORIGFUNCNAME$, "(")) THEN
	WRITELN g_FUNCTYPE$, " ", g_FUNCNAME$, "(void) {" TO tmp_HFILE
    ELSE
	WRITELN g_FUNCTYPE$, " ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE
    END IF

    ' Add function body
    WRITELN g_STRINGARGS$ TO tmp_HFILE
    OPEN g_CFILE$ FOR READING AS g_CFILE
    WHILE NOT(ENDFILE(g_CFILE)) DO
        READLN line$ FROM g_CFILE
        IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE
    WEND
    CLOSE FILE g_CFILE

    WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE

    ' Make sure the function always returns something
    IF INSTR(g_FUNCTYPE$, "char*") THEN WRITELN "return (\"\");}" TO tmp_HFILE
    ELSE WRITELN "return (0);}" TO tmp_HFILE

	CLOSE FILE tmp_HFILE
	
    ' Include header file
    IF NOT(INSTR(g_INCLUDE_FILES$, CONCAT$(LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h"))) THEN
	g_INCLUDE_FILES$ = CONCAT$(g_INCLUDE_FILES$, " ", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")
    END IF

    ' Add to total filelist
    g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")

    ' Delete temp funcfile
    DELETE FILE g_CFILE$

    ' Restore mainfile
    g_CFILE$ = g_COPY_CFILE$
    OPEN g_CFILE$ FOR APPENDING AS g_CFILE

    ' Restore CATCH routine
    g_CATCHGOTO$ = g_ORIGCATCHGOTO$

    ' Clear function variables
    g_ORIGFUNCNAME$ = ""
    g_FUNCNAME$ = ""
    g_FUNCTYPE$ = ""
    g_LOCALSTRINGS$ = ""
    g_STRINGARRAYS$ = ""
    g_STRINGARGS$ = ""

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Return(STRING arg$)

    LOCAL type$, thearg$
    LOCAL dim, x

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty RETURN at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    type$ = Check_Type$(g_CFILE$, arg$, 0)

   ' Check type of var, func using string but returning a value? See also PRINT miniparser
    IF REGEX(arg$, "^VAL *\\(|^INSTR *\\(|^LEN *\\(|^SEARCH *\\(|^ASC *\\(|^FILE *\\(|^REGEX *\\(|^INSTRREV *\\(") THEN
	g_FUNCTYPE$ = "double "
	thearg$ = arg$

    ' Check type of var, string or normal string?
    ELIF INSTR(arg$, g_STRINGSIGN$) OR INSTR(arg$, CHR$(34)) OR INSTR(g_FUNCNAME$, g_STRINGSIGN$) THEN
	g_FUNCTYPE$ = "char* "
	WRITELN "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0; if(", arg$, " != NULL)" TO g_CFILE
	WRITELN " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], ", arg$, ");}" TO g_CFILE
	WRITELN "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" TO g_CFILE
	thearg$ = "__b2c__rbuffer[__b2c__rbuffer_ptr]"

    ' Check if float
    ELIF INSTR(arg$, ".") THEN
	g_FUNCTYPE$ = "double "
	thearg$ = arg$

    ' Check if no alpha chars (then integer value)
    ELIF REGEX(arg$, "[0-9]") THEN
	g_FUNCTYPE$ = "long "
	thearg$ = arg$

    ' Assume variable, check if declared before
    ELIF ISTRUE(LEN(type$)) THEN
	IF INSTR(type$, "DIR* ") THEN
		g_FUNCTYPE$ = "DIR* "
	ELIF INSTR(type$, "FILE ") THEN
		g_FUNCTYPE$ = "FILE* "
	ELIF INSTR(type$, "int* ") THEN
		g_FUNCTYPE$ = "int* "
	ELIF INSTR(type$, "float* ") THEN
		g_FUNCTYPE$ = "float* "
	ELIF INSTR(type$, "double* ") THEN
		g_FUNCTYPE$ = "double* "
	ELIF INSTR(type$, "char* ") OR INSTR(type$, "STRING ") THEN
		g_FUNCTYPE$ = "char* "
	ELIF INSTR(type$, "long* ") THEN
		g_FUNCTYPE$ = "long* "
	ELIF INSTR(type$, "void* ") THEN
		g_FUNCTYPE$ = "void* "
	ELIF INSTR(type$, "int ") THEN
		g_FUNCTYPE$ = "int "
	ELIF INSTR(type$, "float ") THEN
		g_FUNCTYPE$ = "float "
	ELIF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN
		g_FUNCTYPE$ = "double "
	ELIF INSTR(type$, "char ") THEN
		g_FUNCTYPE$ = "char "
	ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
		g_FUNCTYPE$ = "long "
	ELIF INSTR(type$, "void ") THEN
		g_FUNCTYPE$ = "void "
	END IF
	thearg$ = arg$

    ' Not declared, assume integer variable
    ELSE
	g_FUNCTYPE$ = "long "
	thearg$ = arg$
    END IF

    ' Free strings variables if there are any
    SPLIT g_LOCALSTRINGS$ BY " " TO element$ SIZE dim
    FOR x = 1 TO dim
	IF LEN(element$[x]) > 0 THEN WRITELN "if(", element$[x], " != NULL) free(", element$[x], ");" TO g_CFILE
    NEXT
    WRITELN g_STRINGARRAYS$ TO g_CFILE

    ' The actual return value
    WRITELN "return (", thearg$, ");" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Deffn(STRING arg$)

    LOCAL sym$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(arg$)) THEN
	PRINT NL$, "ERROR: empty DEF FN at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Translate to C macro
    sym$ = CHOP$(MID$(arg$, INSTR(arg$, " ")))

    WRITELN "#define ", LEFT$(sym$, INSTR(sym$, "=") -1), " (", MID$(sym$, INSTR(sym$, "=") + 1), ")" TO g_HFILE

    ' Make symbol known to parser
    g_IMPORTED$ = CONCAT$(LEFT$(sym$, INSTR(sym$, "(") - 1), " ", g_IMPORTED$)

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Const(STRING arg$)

    ' Check if we have an argument at all
    IF ISFALSE(LEN(arg$)) THEN
	PRINT NL$, "ERROR: empty CONST at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    WRITELN "#define ", LEFT$(arg$, INSTR(arg$, "=") - 1), " (", MID$(arg$, INSTR(arg$, "=") + 1), ")" TO g_HFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Push(STRING arg$)

    LOCAL type$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty PUSH at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    IF NOT(INSTR(arg$, ".")) THEN
	type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
	    type$ = Check_Type$(g_CFILE$, arg$, 0)
	END IF
    END IF

    ' Allocate space for type
    WRITELN "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" TO g_CFILE

    ' Check type of var, string?
    IF INSTR(arg$, g_STRINGSIGN$) THEN
	WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE
	WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = strdup(", arg$, ");" TO g_CFILE
	WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE
    ' Check if it is a normal string
    ELIF INSTR(arg$, CHR$(34)) THEN
	WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE
	WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = strdup(", arg$, ");" TO g_CFILE
	WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE
    ' Check if float
    ELIF INSTR(arg$, ".") THEN
	WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE
	WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
	WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE
    ' Check if no alpha chars (then integer value)
    ELIF NOT(REGEX(arg$, "[a-zA-Z]")) THEN
	WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE
	WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
	WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE
    ' Assume variable, check if declared before
    ELIF ISTRUE(LEN(type$)) THEN
	IF REGEX(type$, "double .*") THEN
	    WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE
	    WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
	    WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE
	ELSE
	    WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE
	    WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
	    WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE
	END IF
    ' Not declared, assume integer variable
    ELSE
	WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE
	WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
	WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE
    END IF

    ' Increase stackpointer
    WRITELN "__b2c__stackptr++;" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Pull(STRING arg$)

    LOCAL check
    LOCAL type$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty PULL at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Argument must be a variable
    IF NOT(REGEX(arg$, "[a-zA-Z]+.*")) THEN
	PRINT NL$, "ERROR: argument in PULL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' is not a variable!"
	END 1
    END IF

    ' Decrease stackpointer again
    WRITELN "__b2c__stackptr--;" TO g_CFILE
    WRITELN "if(__b2c__stackptr < 0) __b2c__stackptr=0;" TO g_CFILE

    ' Get the last value from stack
    IF INSTR(arg$, g_STRINGSIGN$) THEN
	check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
	ENDIF

	IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE

	WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE
	WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE
    ELSE
	' Variable may not be array, these should be defined with DECLARE
	IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN
	    ' Not declared? Assume long
	    check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	    IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0)

	    IF ISFALSE(check) THEN WRITELN "long ", arg$, "; /* pull */" TO g_HFILE
	END IF

	' See how var was declared
	type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
	    type$ = Check_Type$(g_CFILE$, arg$, 0)
	END IF

	' Make sure internal var is copied to var of program
	IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN
	    WRITELN "if(__b2c__typestack[__b2c__stackptr] == 2) ", arg$, "=__b2c__doublestack[__b2c__stackptr];" TO g_CFILE
	ELIF INSTR(type$, "long ") OR INSTR(type$, "int ") OR INSTR(type$, "NUMBER ") THEN
	    WRITELN "if(__b2c__typestack[__b2c__stackptr] == 3) ", arg$, "=__b2c__longstack[__b2c__stackptr];" TO g_CFILE
	ELSE
	    WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE
	    WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE
	    WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE
	END IF
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Import(STRING arg$)

    LOCAL lib$, type$, sym$, tmp$, token$, alias$
    LOCAL check

    ' Check if FROM is available
    IF NOT(INSTR(arg$, " FROM ")) THEN
	PRINT NL$, "ERROR: missing FROM in IMPORT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the symbolname without surrounding spaces and doublequotes
    IF INSTR(arg$, "(") THEN
	sym$ = REPLACE$((CHOP$(LEFT$(arg$, INSTR(arg$, "(") - 1))), CHR$(34), "")
	tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))
	token$ = CHOP$(MID$(arg$, 1, INSTRREV(arg$, ")") - 1))
    ELSE
	sym$ = REPLACE$((CHOP$(MID$(arg$, 1, INSTR(arg$, " FROM ") - 1))), CHR$(34), "")
	tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))
	token$ = ""
    END IF

    ' Check if TYPE is available
    IF NOT(INSTR(arg$, " TYPE ")) THEN
	PRINT NL$, "ERROR: missing TYPE in IMPORT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get library and type
    lib$ = CHOP$(MID$(tmp$, 1, INSTR(tmp$, " TYPE ")))
    type$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TYPE ") + 6))

    ' Check if ALIAS is there
    IF INSTR(type$, " ALIAS ") THEN
	alias$ = REPLACE$(MID$(type$, INSTR(type$, " ALIAS ") + 7), CHR$(34), "")
	WRITELN "#define ", alias$, " ", sym$ TO g_HFILE
	g_IMPORTED$ = CONCAT$(alias$, " ", g_IMPORTED$)
	type$ = LEFT$(type$, INSTR(type$, " ALIAS ") - 1)
    ENDIF

    ptr$ = REPLACE$(REPLACE$(lib$, CHR$(34), ""), "-", "")
    ptr$ = REPLACE$(REPLACE$(REPLACE$(ptr$, ".", ""), "/", ""), "_", "")

    ' If library is libm or libc, skip dlopen as we're linking with those anyway
    IF NOT(INSTR(lib$, "libc.so") ) AND NOT(INSTR(lib$, "libm.so")) THEN

	' Check if variable was declared
	check = Search(g_CFILE$, CONCAT$("void* __b2c__dlopen__pointer_", ptr$, ";"), 0)
	IF check < 0 THEN
	    WRITELN "void* __b2c__dlopen__pointer_", ptr$, ";" TO g_CFILE
	    WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", lib$, ", RTLD_LAZY);" TO g_CFILE
	END IF
	WRITELN "if(__b2c__dlopen__pointer_", ptr$, " == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE

	' Check if token was declared
	check = Search(g_HFILE$, CONCAT$(type$, "(\\*", sym$, ")"), g_HEADER_SEARCHPOS)
	IF check < 0 THEN
	    WRITELN type$, "(*", sym$, ")(", MID$(token$, INSTR(token$, "(") + 1), ");" TO g_HFILE
	END IF

	' Translate to C function
	WRITELN "*(", type$, "**) (&", sym$, ") = dlsym(__b2c__dlopen__pointer_", ptr$, ", \"", sym$, "\");" TO g_CFILE
	WRITELN "if(", sym$, " == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
    END IF

    ' Make symbol known to parser
    g_IMPORTED$ = CONCAT$(sym$, " ", g_IMPORTED$)

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Declare(STRING arg$)

    LOCAL var$, type$, new$, value$
    LOCAL i, dim, check, option

    '  Check on a GLOBAL RECORD
    IF INSTR(arg$, "RECORD ") THEN
	' Translate to C typedef struct
	g_RECORDNAME$ = CONCAT$("RECORD_", STR$(g_COUNTER))
	WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE
	g_RECORDVAR$ = MID$(CHOP$(arg$), INSTR(CHOP$(arg$), " ") + 1)
	' Store current function name
	IF LEN(g_FUNCNAME$) > 0 THEN
	    g_RECORDCACHE$ = g_FUNCNAME$
	    g_FUNCNAME$ = ""
	END IF
    ELSE
	' Get the variablename and type
	IF INSTR(arg$, " TYPE ") THEN
	    var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE ")))
	    type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6))
	ELIF INSTR(arg$, " ASSOC ") THEN
	    var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " ASSOC ")))
	    type$ = CHOP$(MID$(arg$, INSTR(arg$, " ASSOC ") + 7))
	ELSE
	    var$ = CHOP$(arg$)
	    type$ = "long"
	END IF

	' Check if variable was already declared
	IF NOT(INSTR(var$, ".")) THEN check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
	ELSE check = FALSE

	IF ISTRUE(check) THEN
	    PRINT NL$, "ERROR: variable in DECLARE or GLOBAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
	    END 1
	END IF

	' If array, increase dimensions when OPTION BASE is set
	IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN
	    new$ = ""
	    REPEAT
		new$ = CONCAT$(new$, LEFT$(var$, INSTR(var$, "[") - 1), "[")
		value$ = MID$(var$, INSTR(var$, "[") + 1)
		new$ = CONCAT$(new$, MID$(value$, 1, INSTR(value$, "]") - 1), "+", STR$(g_OPTION_BASE), "]")
		var$ = MID$(var$, INSTR(var$, "]") + 1)
	    UNTIL NOT(REGEX(var$, "\\[.*\\]"))
	    var$ = new$
	END IF

	' Check for associative array
	IF INSTR(arg$, " ASSOC ") THEN
	    SPLIT var$ BY "," TO str$ SIZE dim
	    FOR i = 1 TO dim
		WRITELN "struct __b2c__", CHOP$(str$[i]), "_type {char *key; /* noparse */ ", type$, " value; /* noparse */ };" TO g_HFILE
		WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__", CHOP$(str$[i]), " = { NULL }; long __b2c__", CHOP$(str$[i]), "_idx = 0;" TO g_HFILE

		WRITELN "static int __b2c__", CHOP$(str$[i]), "_comp(const void *__b2c__m1, const void *__b2c__m2){ " TO g_HFILE
		WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__mi1 = (struct __b2c__", CHOP$(str$[i]), "_type *) __b2c__m1;" TO g_HFILE
		WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__mi2 = (struct __b2c__", CHOP$(str$[i]), "_type *) __b2c__m2;" TO g_HFILE
		WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key == NULL) return 0;" TO g_HFILE
		WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key != NULL) return -1;" TO g_HFILE
		WRITELN "if(__b2c__mi1->key != NULL && __b2c__mi2->key == NULL) return 1;" TO g_HFILE
		WRITELN "return strcmp(__b2c__mi1->key, __b2c__mi2->key); }" TO g_HFILE

		WRITELN "struct __b2c__", CHOP$(str$[i]), "_type * __b2c__", CHOP$(str$[i]), "_exist (char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type __b2c__", CHOP$(str$[i]), "_key, *__b2c__", CHOP$(str$[i]), "__result;" TO g_HFILE
		WRITELN "qsort(__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
		WRITELN "__b2c__", CHOP$(str$[i]), "_key.key = __b2c__index; __b2c__", CHOP$(str$[i]), "__result = bsearch(&__b2c__", CHOP$(str$[i]), "_key, __b2c__", CHOP$(str$[i]), "," TO g_HFILE
		WRITELN "__b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
		WRITELN "return(__b2c__", CHOP$(str$[i]), "__result); }" TO g_HFILE

		WRITELN "void __b2c__", CHOP$(str$[i]), "__add(char *__b2c__index){__b2c__", CHOP$(str$[i]), "_idx++;" TO g_HFILE
		WRITELN "__b2c__", CHOP$(str$[i]), " = (struct __b2c__", CHOP$(str$[i]), "_type *) realloc (__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx * sizeof (struct __b2c__", CHOP$(str$[i]), "_type));" TO g_HFILE
		WRITELN "__b2c__", CHOP$(str$[i]), "[__b2c__", CHOP$(str$[i]), "_idx - 1].key = strdup (__b2c__index); __b2c__", CHOP$(str$[i]), "[__b2c__", CHOP$(str$[i]), "_idx-1].value = 0;}" TO g_HFILE

		WRITELN "void __b2c__", CHOP$(str$[i]), "__del(char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type *__b2c__", CHOP$(str$[i]), "__location = __b2c__", CHOP$(str$[i]), "_exist(__b2c__index);" TO g_HFILE
		WRITELN "if(__b2c__", CHOP$(str$[i]), "__location != NULL) {free(__b2c__", CHOP$(str$[i]), "__location->key); __b2c__", CHOP$(str$[i]), "__location->key = NULL;} }" TO g_HFILE

		WRITELN type$, " ", CHOP$(str$[i]), "(char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type __b2c__", CHOP$(str$[i]), "_key, *__b2c__", CHOP$(str$[i]), "__result;" TO g_HFILE
		WRITELN "qsort(__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
		WRITELN "__b2c__", CHOP$(str$[i]), "_key.key = __b2c__index; __b2c__", CHOP$(str$[i]), "__result = bsearch(&__b2c__", CHOP$(str$[i]), "_key, __b2c__", CHOP$(str$[i]), "," TO g_HFILE
		WRITELN "__b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
		IF INSTR(str$[i], g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN
		    WRITELN "if(__b2c__", CHOP$(str$[i]), "__result == NULL) return(\"\"); return __b2c__", CHOP$(str$[i]), "__result->value;}" TO g_HFILE
		ELSE
		    WRITELN "if(__b2c__", CHOP$(str$[i]), "__result == NULL) return(0); return __b2c__", CHOP$(str$[i]), "__result->value;}" TO g_HFILE
		END IF
	    NEXT

	' Check if var is string var
	ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND NOT(INSTR(var$, "=")) THEN
	    check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS)
	    IF check < 0 THEN
		SPLIT CHOP$(var$) BY "," TO str$ SIZE dim
		FOR i = 1 TO dim
		    IF INSTR(str$[i], "[") THEN
			WRITELN "char *", CHOP$(str$[i]), " = { NULL };" TO g_HFILE
		    ELSE
			WRITELN "char *", CHOP$(str$[i]), " = NULL; " TO g_HFILE
			' Pointer var should not be initialized
			IF INSTR(var$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE
		    END IF
		NEXT
	    END IF
        ' Var is string array assignment
	ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN
            WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
            option = g_OPTION_BASE
            WHILE option > 0
                WRITELN " \"\", " TO g_HFILE
                DECR option
            WEND
	    WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE

	' Assume char assignment or number
	ELSE
	    IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
		SPLIT var$ BY "," TO str$ SIZE dim
		FOR i = 1 TO dim
		    WRITELN type$, " ", str$[i], " = { 0 };" TO g_HFILE
		NEXT
	    ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
                WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
                option = g_OPTION_BASE
                WHILE option > 0
                    WRITELN " 0, " TO g_HFILE
                    DECR option
                WEND
	        WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
	    ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
		WRITELN type$, " ", var$, ";" TO g_HFILE
		WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE
	    ELSE
		WRITELN type$, " ", var$, ";" TO g_HFILE
            END IF
	ENDIF
    ENDIF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Local(STRING arg$)

    LOCAL var$, type$, new$, value$, dim$
    LOCAL check, i, dim, option

    ' Get the variablename and type
    IF INSTR(arg$, " TYPE ") THEN
	var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE ")))
	type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6))
    ELSE
	var$ = CHOP$(arg$)
	IF INSTR(var$, g_STRINGSIGN$) THEN
	    type$ = "char*"
	ELSE
	    type$ = "long"
	END IF
    END IF

    check = 0

    ' Check if variable was already declared
    IF NOT(INSTR(var$, ".")) THEN
	IF LEN(g_FUNCNAME$) > 0 THEN check = Check_Declared(g_CFILE$, var$, 0)
	ELSE check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
    END IF

    IF ISTRUE(check) THEN
	PRINT NL$, "ERROR: variable in LOCAL statement at line ", g_COUNTER, " in file '", g_CURFILE$, "' was defined previously!"
	END 1
    END IF

    ' If array, increase dimensions when OPTION BASE is set
    IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN
	new$ = ""
	REPEAT
	    new$ = CONCAT$(new$, LEFT$(var$, INSTR(var$, "[") - 1), "[")
	    value$ = MID$(var$, INSTR(var$, "[") + 1)
	    new$ = CONCAT$(new$, MID$(value$, 1, INSTR(value$, "]") - 1), "+", STR$(g_OPTION_BASE), "]")
	    var$ = MID$(var$, INSTR(var$, "]") + 1)
	UNTIL NOT(REGEX(var$, "\\[.*\\]"))
	var$ = new$
    END IF

    ' Check if var is string var
    IF ( REGEX(type$, "STRING|char\\*$") OR INSTR(var$, g_STRINGSIGN$) ) AND NOT(INSTR(var$, "=")) AND NOT(REGEX(type$, ".+\\[.+\\$\\]")) THEN
	check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", var$, " = NULL;"), 0)
	ENDIF

	IF check < 0 THEN
	    SPLIT var$ BY "," TO str$ SIZE dim
	    FOR i = 1 TO dim
		' Check on multidimensional stringarrays
		IF REGEX(str$[i], "\\[.*\\]\\[") THEN
		    PRINT NL$, "ERROR: multidimensional stringarrays at line ", g_COUNTER, " in file '", g_CURFILE$, "' are not supported!"
		    END 1
		END IF

		' Are we in a function?
		IF ISTRUE(LEN(g_FUNCNAME$)) THEN
		    IF ISTRUE(LEN(g_RECORDNAME$)) THEN
			IF REGEX(str$[i], "\\[.*\\]") THEN
			    WRITELN "char *", CHOP$(str$[i]), ";" TO g_CFILE
			    dim$ = MID$(str$[i], INSTR(str$[i], "[") + 1)
			    g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<", LEFT$(dim$, INSTR(dim$, "]") - 1), "; __b2c__ctr++)if(", g_RECORDVAR$, ".", LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]!=NULL){free(", g_RECORDVAR$, ".", LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]);}")
			ELSE
			    WRITELN "char *", CHOP$(str$[i]), "; /* noparse */" TO g_CFILE
			END IF
		    ELSE
			IF REGEX(str$[i], "\\[.*\\]") THEN
			    WRITELN "char *", CHOP$(str$[i]), " = { NULL};" TO g_CFILE
			    dim$ = MID$(str$[i], INSTR(str$[i], "[") + 1)
			    g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<", LEFT$(dim$, INSTR(dim$, "]") - 1), "; __b2c__ctr++)if(", g_WITHVAR$, LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]!=NULL){free(", g_WITHVAR$, LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]);}")
			ELSE
			    WRITELN "char *", CHOP$(str$[i]), " = NULL;" TO g_CFILE
			    ' Pointer var should not be initialized
			    IF INSTR(var$, g_STRINGSIGN$) THEN
				WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE
				g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(str$[i]))
			    END IF
			END IF
		    END IF
		' We are in the mainprogram
		ELSE
		    IF ISTRUE(LEN(g_RECORDNAME$)) THEN
			WRITELN "char *", CHOP$(str$[i]), "; /* noparse */" TO g_HFILE
		    ELSE
			IF REGEX(str$[i], "\\[.*\\]") THEN
			    WRITELN "char *", CHOP$(str$[i]), " = { NULL };" TO g_CFILE
			ELSE
			    WRITELN "char *", CHOP$(str$[i]), " = NULL; " TO g_HFILE
			    ' Pointer var should not be initialized
			    IF INSTR(var$, g_STRINGSIGN$) THEN WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE
			END IF
		    END IF
		END IF
	    NEXT
	END IF
    ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN
	IF ISTRUE(LEN(g_FUNCNAME$)) THEN
            ' String array assignment
            WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE
            option = g_OPTION_BASE
            WHILE option > 0
                WRITELN " \"\", " TO g_CFILE
                DECR option
            WEND
	    WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE
        ELSE
            ' String array assignment
            WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
            option = g_OPTION_BASE
            WHILE option > 0
                WRITELN " \"\", " TO g_HFILE
                DECR option
            WEND
	    WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
        END IF
    ' Assume number
    ELSE
	IF ISTRUE(LEN(g_FUNCNAME$)) THEN
	    IF ISTRUE(LEN(g_RECORDNAME$)) THEN
		WRITELN type$, " ", var$, "; /* noparse */" TO g_CFILE
	    ELSE
		IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
		    SPLIT var$ BY "," TO str$ SIZE dim
		    FOR i = 1 TO dim
			WRITELN type$, " ", str$[i], " = { 0 };" TO g_CFILE
		    NEXT
		ELIF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
                    ' Numeric array assignment
                    WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE
                    option = g_OPTION_BASE
                    WHILE option > 0
                        WRITELN " 0, " TO g_CFILE
                        DECR option
                    WEND
	            WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE
		ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
		    WRITELN type$, " ", var$, ";" TO g_CFILE
		    WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE
		ELSE
		    WRITELN type$, " ", var$, ";" TO g_CFILE
		END IF
	    END IF
	ELSE
	    IF ISTRUE(LEN(g_RECORDNAME$)) THEN
		WRITELN type$, " ", var$, "; /* noparse */" TO g_HFILE
	    ELSE
		IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
		    SPLIT var$ BY "," TO str$ SIZE dim
		    FOR i = 1 TO dim
			WRITELN type$, " ", str$[i], " = { 0 };" TO g_HFILE
		    NEXT
		ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
                    ' Numeric array assignment
                    WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
                    option = g_OPTION_BASE
                    WHILE option > 0
                        WRITELN " 0, " TO g_HFILE
                        DECR option
                    WEND
	            WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
                ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
		    WRITELN type$, " ", var$, ";" TO g_HFILE
		    WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE
		ELSE
		    WRITELN type$, " ", var$, ";" TO g_HFILE
                END IF
	    END IF
	END IF
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Read(STRING arg$)

    LOCAL check
    LOCAL type$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty READ at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check type of var, string?
    IF EQUAL(RIGHT$(arg$, LEN(g_STRINGSIGN$)), g_STRINGSIGN$) THEN
	check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
	ENDIF

	IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE

	' Convert to C
	WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE
	WRITELN "strcpy(", arg$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE
	WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE
    ELSE
	' Variable may not be array, these should be defined with DECLARE
	IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN
	    ' Not declared? Assume long
	    check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	    IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0)

	    IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE
	END IF

	' See how var was declared
	type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
	    type$ = Check_Type$(g_CFILE$, arg$, 0)
	END IF

	' Convert to C
	IF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN
	    WRITELN arg$, " = __b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE
	    WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
	ELIF INSTR(type$, "float ") THEN
	    WRITELN arg$, " = (float)__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE
	    WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
	ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
	    WRITELN arg$, " = __b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE
	    WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
	ELIF INSTR(type$, "int ") THEN
	    WRITELN arg$, " = (int)__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE
	    WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
	ELSE
	    WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE
	    WRITELN "strcpy(", arg$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE
	    WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE
	END IF
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Color(STRING arg$)

    LOCAL dim
    LOCAL BFG$, COL$

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty COLOR at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    SPLIT arg$ BY " " TO element$ SIZE dim

    ' Check if we need to reset
    IF EQUAL(element$[1], "RESET") THEN
	WRITELN "fprintf(stdout,\"\\033[0m\");" TO g_CFILE
    ELIF EQUAL(element$[1], "INTENSE") THEN
	WRITELN "fprintf(stdout,\"\\033[1m\");" TO g_CFILE
    ELIF EQUAL(element$[1], "INVERSE") THEN
	WRITELN "fprintf(stdout,\"\\033[7m\");" TO g_CFILE
    ELIF EQUAL(element$[1], "NORMAL") THEN
	WRITELN "fprintf(stdout,\"\\033[22m\");" TO g_CFILE
    ' Check if TO is available
    ELIF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in COLOR statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    ELSE
	' Get the target and colorname
	SELECT element$[1]
	    CASE "FG"
		BFG$ = "3"
	    CASE "BG"
		BFG$ = "4"
	    DEFAULT
		IF REGEX(element$[1], "0|1") THEN BFG$ = STR$(VAL(element$[1]) + 3)
		ELSE BFG$ = element$[1]
	END SELECT

	SELECT element$[3]
	    CASE "BLACK"
		COL$ = "0"
	    CASE "RED"
		COL$ = "1"
	    CASE "GREEN"
		COL$ = "2"
	    CASE "YELLOW"
		COL$ = "3"
	    CASE "BLUE"
		COL$ = "4"
	    CASE "MAGENTA"
		COL$ = "5"
	    CASE "CYAN"
		COL$ = "6"
	    CASE "WHITE"
		COL$ = "7"
	    DEFAULT
		COL$ = element$[3]
	END SELECT

	' Now select color
	WRITELN "fprintf(stdout,\"\\033[%ld%ldm\", (long)", BFG$, ", (long)", COL$, ");" TO g_CFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Gotoxy(STRING arg$)

    LOCAL dim

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty GOTOXY at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the target and colorname
    SPLIT arg$ BY "," TO element$ SIZE dim

    IF dim EQ 1 THEN
	PRINT NL$, "ERROR: missing coordinate in GOTOXY at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Translate to C
    WRITELN "fprintf(stdout, \"\\033[%ld;%ldH\",(long)(", CHOP$(element$[2]), "), (long)(", CHOP$(element$[1]), ")); fflush(stdout);" TO g_CFILE

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Split(STRING arg$)

    LOCAL source$, rest$, by$, to$, size$
    LOCAL check

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty SPLIT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if BY is available
    IF NOT(INSTR(arg$, " BY ")) THEN
	PRINT NL$, "ERROR: Missing BY in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if SIZE is available
    IF NOT(INSTR(arg$, " SIZE ")) THEN
	PRINT NL$, "ERROR: Missing SIZE in SPLIT statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the source string
    source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " BY ") - 1))
    rest$ = MID$(arg$, INSTR(arg$, " BY ") + 4)

    by$ = CHOP$(LEFT$(rest$, INSTR(rest$, " TO ") - 1))
    rest$ = MID$(rest$, INSTR(rest$, " TO ") + 4)

    to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1))
    size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6))

    ' Variable may not be array, these should be defined with DECLARE
    IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN
	check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0)

	IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE
    END IF

    ' Translate to C code
    IF ISTRUE(LEN(g_FUNCNAME$)) THEN
	IF NOT(INSTR(g_STRINGARGS$, CONCAT$("**", to$))) THEN
	    g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char **", to$, " = NULL; int __b2c__split__", to$, " = ", STR$(g_OPTION_BASE), ";")
	END IF
    ELSE
	check = Search(g_HFILE$, CONCAT$(to$, " = NULL;"), g_HEADER_SEARCHPOS)
	IF check < 0 THEN
	    WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE
	END IF
    END IF

    ' If the split array was used before in a loop, clear it
    WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr<=__b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE
    WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE

    ' Run the SPLIT code
    WRITELN "if (", source$, " != NULL && strlen(", source$, ") > 0 && ", by$, " != NULL && strlen(", by$, ")>0){__b2c__split_tmp = strdup(", source$, "); __b2c__split_ptr = __b2c__split_tmp; while((__b2c__split = strstr(__b2c__split_tmp, ", by$, ")) != NULL)" TO g_CFILE
    WRITELN "{if(__b2c__split-__b2c__split_tmp >= 0) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); if(__b2c__split-__b2c__split_tmp == 0) {", to$, "[__b2c__split__", to$, "] = calloc(1, sizeof(char)); if (__b2c__collapse == 0)" TO g_CFILE
    WRITELN "__b2c__split__", to$, "++; else free(", to$, "[__b2c__split__", to$, "]);} else ", to$, "[__b2c__split__", to$, "++] = __b2c__strndup(__b2c__split_tmp, __b2c__split-__b2c__split_tmp);}" TO g_CFILE
    WRITELN "__b2c__split_tmp = __b2c__split + strlen(", by$, ");} if(strlen(__b2c__split_tmp) >= 0) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); if(strlen(__b2c__split_tmp) == 0) {" TO g_CFILE
    WRITELN to$, "[__b2c__split__", to$, "] = calloc(1, sizeof(char)); if (__b2c__collapse == 0) __b2c__split__", to$, "++; else free(", to$, "[__b2c__split__", to$, "]);}" TO g_CFILE
    WRITELN "else ", to$, "[__b2c__split__", to$, "++] = strdup(__b2c__split_tmp);} free(__b2c__split_ptr);} ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, "; if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE

    ' Add declared array to array list if we are in a function
    IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, CONCAT$(to$, "["))) THEN
	g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " if(", to$, "!= NULL){for(__b2c__ctr=", STR$(g_OPTION_BASE), ";__b2c__ctr<=__b2c__split__", to$, ";__b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){free(", to$, "[__b2c__ctr]);}free(", to$, ");}")
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Sort(STRING arg$)

    LOCAL dim$, type$, var$, down$
    LOCAL check

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty SORT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

     ' Check on SIZE argument
    IF INSTR(arg$, "SIZE") THEN
	dim$ = CHOP$(MID$(arg$, INSTR(arg$, "SIZE") + 5))
	var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "SIZE") - 1))
    ELSE
	var$ = arg$
    END IF

    ' Check on DOWN argument
    IF INSTR(arg$, "DOWN") THEN
	IF LEN(dim$) > 0 THEN dim$ = CHOP$(LEFT$(dim$, INSTR(dim$, "DOWN") - 1))
	var$ = CHOP$(LEFT$(var$, INSTR(var$, "DOWN") - 1))
	down$ = "_down"
    ELSE
	down$ = ""
    END IF

    ' Declared before?
    IF INSTR(var$, g_STRINGSIGN$) THEN
	check = Search(g_HFILE$, CONCAT$("char *", var$, "["), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("char *", var$, "["), 0)
	ENDIF
    ELSE
	check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)
    END IF

    ' Verify if the array was declared at SPLIT
    IF check < 0 THEN
	check = Search(g_HFILE$, CONCAT$("__b2c__split__", var$), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
	    check = Search(g_CFILE$, CONCAT$("__b2c__split__", var$), 0)
	ENDIF
	IF ISFALSE(check) THEN
	    PRINT NL$, "ERROR: argument to SORT not an array at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	    END 1
	ELIF LEN(dim$) IS 0 THEN
	    dim$ = CONCAT$("__b2c__split__", var$, "+1")
	END IF
    ELIF LEN(dim$) IS 0 THEN
	' See how var was declared
	type$ = Check_Type$(g_HFILE$, CONCAT$(var$, "["), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
	    type$ = Check_Type$(g_CFILE$, CONCAT$(var$, "["), 0)
	ENDIF
	dim$ = MID$(type$, INSTR(type$, "[") + 1, INSTR(type$, "]") - INSTR(type$, "[") - 1)
    END IF

    ' Check if we have a string
    IF INSTR(var$, g_STRINGSIGN$) THEN
	WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(char*), __b2c__sortstr", down$, ");" TO g_CFILE
    ' It is a value
    ELSE
	' See how var was declared
	type$ = Check_Type$(g_HFILE$, CONCAT$(var$, "["), g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, CONCAT$(var$, "["), 0)

	IF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN
	    WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(double), __b2c__sortnrd", down$, ");" TO g_CFILE
	ELIF INSTR(type$, "float ") THEN
	    WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(float), __b2c__sortnrf", down$, ");" TO g_CFILE
	ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
	    WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(long), __b2c__sortnrl", down$, ");" TO g_CFILE
	ELSE
	    WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, "-", g_OPTION_BASE, ", sizeof(int), __b2c__sortnri", down$, ");" TO g_CFILE
	END IF
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Alias(STRING arg$)

    LOCAL dim

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty ALIAS at at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the target and colorname
    SPLIT REPLACE$(arg$, CHR$(34), "") BY "TO" TO element$ SIZE dim

    IF dim EQ 1 THEN
	PRINT NL$, "ERROR: missing TO in ALIAS statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Translate to C
    WRITELN "#define ", element$[2], " ", element$[1] TO g_HFILE
    g_IMPORTED$ = CONCAT$(element$[2], " ", g_IMPORTED$)

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Lookup(STRING arg$)

    LOCAL source$, rest$, to$, size$
    LOCAL check

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty LOOKUP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in LOOKUP statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if SIZE is available
    IF NOT(INSTR(arg$, " SIZE ")) THEN
	PRINT NL$, "ERROR: Missing SIZE in LOOKUP statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the source string
    source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
    rest$ = MID$(arg$, INSTR(arg$, " TO ") + 4)

    to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1))
    size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6))

    ' Variable may not be array, these should be defined with DECLARE
    IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN
	check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
	IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0)

	IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE
    END IF

    ' Translate to C code
    IF ISTRUE(LEN(g_FUNCNAME$)) THEN
	IF NOT(INSTR(g_STRINGARGS$, CONCAT$("**", to$))) THEN
	    g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char **", to$, " = NULL; int __b2c__split__", to$, " = ", STR$(g_OPTION_BASE), ";")
	END IF
    ELSE
	check = Search(g_HFILE$, CONCAT$(to$, " = NULL;"), g_HEADER_SEARCHPOS)
	IF check < 0 THEN
	    WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE
	END IF
    END IF

    ' If the split array was used before in a loop, clear it
    WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr <= __b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE
    WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE

    ' Run the LOOKUP code
    WRITELN "for(__b2c__ctr = ", g_OPTION_BASE, "; __b2c__ctr < __b2c__", source$, "_idx + ", g_OPTION_BASE, "; __b2c__ctr++)" TO g_CFILE
    WRITELN "{", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*));" TO g_CFILE
    WRITELN to$, "[__b2c__split__", to$, "++] = strdup(__b2c__", source$, "[__b2c__ctr-", g_OPTION_BASE, "].key);} ",  size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, ";if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE

    ' Add declared array to array list if we are in a function
    IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, CONCAT$(to$, "["))) THEN
	g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " if(", to$, "!= NULL){for(__b2c__ctr=", STR$(g_OPTION_BASE), ";__b2c__ctr<=__b2c__split__", to$, ";__b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){free(", to$, "[__b2c__ctr]);}free(", to$, ");}")
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Relate(STRING arg$)

    LOCAL source$, to$, txt$
    LOCAL declared, dim, i
    LOCAL thefile TYPE FILE*

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty RELATE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Check if TO is available
    IF NOT(INSTR(arg$, " TO ")) THEN
	PRINT NL$, "ERROR: Missing TO in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Get the source string
    source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
    to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))

    ' CHeck if declared as ASSOC
    OPEN g_HFILE$ FOR READING AS thefile
    SEEK thefile OFFSET g_HEADER_SEARCHPOS

    WHILE NOT(ENDFILE(thefile)) DO
	READLN txt$ FROM thefile
        IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
            declared = REGEX(txt$, CONCAT$("__b2c__", source$, "_type"))
	    IF ISTRUE(declared) THEN BREAK
	END IF
    WEND
    IF NOT(declared) THEN
	PRINT NL$, "ERROR: Variable ", source$, " not declared in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Assign relations
    SPLIT to$ BY "," TO str$ SIZE dim

    FOR i = 1 TO dim

	SEEK thefile OFFSET g_HEADER_SEARCHPOS
	WHILE NOT(ENDFILE(thefile)) DO
	    READLN txt$ FROM thefile
	    IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
		declared = REGEX(txt$, CONCAT$("__b2c__", CHOP$(str$[i]), "_type"))
		IF ISTRUE(declared) THEN BREAK
	    END IF
	WEND
	IF NOT(declared) THEN
	    PRINT NL$, "ERROR: Variable ", CHOP$(str$[i]), " not declared in RELATE statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	    END 1
	END IF

	g_RELATE$[g_RELATE_CTR] = CONCAT$(source$, " ", CHOP$(str$[i]))
	INCR g_RELATE_CTR

    NEXT

    CLOSE FILE thefile

END SUB

'----------------------------------------------------------------------------------------------

SUB Handle_Data(STRING arg$)

    LOCAL in_string, pos, escaped, x

    ' Check if we have an argument at all
    IF ISFALSE(LEN(CHOP$(arg$))) THEN
	PRINT NL$, "ERROR: empty DATA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
	END 1
    END IF

    ' Start miniparser
    in_string = FALSE
    pos = 1
    escaped = 0

    FOR x = 1 TO LEN(arg$)
	IF ISTRUE(EQUAL(MID$(arg$, x, 1), ",")) THEN
	    IF ISFALSE(in_string) THEN
		IF INSTR(MID$(arg$, pos, x-pos), CHR$(34)) THEN
		    WRITELN MID$(arg$, pos, x-pos), ", " TO STRINGARRAYFILE
		ELSE
		    WRITELN MID$(arg$, pos, x-pos), ", " TO FLOATARRAYFILE
		END IF
		pos = x+1
		escaped = FALSE
	    END IF
	ELIF EQUAL(MID$(arg$, x, 1), "\\") THEN
	    escaped = TRUE
	ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), CHR$(34))) THEN
	    IF ISFALSE(escaped) THEN
		in_string = NOT(in_string)
	    END IF
	    escaped = FALSE
	ELSE
	    escaped = FALSE
	ENDIF
    NEXT
    arg$ = MID$(arg$, pos)

    ' Write last element to file
    IF INSTR(arg$, CHR$(34)) THEN
	WRITELN arg$, ", " TO STRINGARRAYFILE
    ELSE
	WRITELN arg$, ", " TO FLOATARRAYFILE
    END IF

END SUB

'----------------------------------------------------------------------------------------------
'
' Simple parser to tokenize line.
'
' Each line should begin with a statement.
' The rest of the line may contain functions, these are
'   converted using C macros.
'
'----------------------------------------------------------------------------------------------

SUB Parse_Line(STRING statement$)

    LOCAL inc$, copy_curfile$, total$, txt$, exp$
    LOCAL dim, i, found, copy_counter, to_parse, size
    LOCAL newfile TYPE FILE*

    SPLIT statement$ BY " " TO element$ SIZE dim

    IF dim > 0 THEN

	' Check if enclosed IF/ELIF/ELSE needs to be closed
	IF g_IF_PARSE IS 1 THEN
	    IF NOT(EQUAL(element$[1], "ELIF")) AND NOT(EQUAL(element$[1], "ELSE")) THEN
		WRITELN "}" TO g_CFILE
		g_IF_PARSE = 0
	    END IF
	END IF

	' In TRACE MODE show linenr and code
	IF g_TRACE IS 1 AND NOT(INSTR(statement$, "FUNCTION ")) AND NOT(INSTR(statement$, "SUB ")) THEN
	    WRITELN "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /* noparse */" TO g_CFILE
	    txt$ = REPLACE$(statement$, CHR$(34), "'")
	    WRITELN "fprintf(stderr, \"", g_CURFILE$, " %d: ", txt$, "\\n\", ", g_COUNTER, "); /* noparse */" TO g_CFILE
	END IF

	' See if we need to pass C code
	IF ISTRUE(g_USE_C) THEN
	    IF EQUAL(LEFT$(statement$, 8), "END USEC") OR EQUAL(element$[1], "ENDUSEC") THEN
		g_USE_C = 0
	    ELSE
		WRITELN statement$ TO g_CFILE
	    END IF

	ELIF EQUAL(LEFT$(element$[1], 2), "#!") THEN
	    'Do nothing

	ELIF EQUAL(LEFT$(element$[1], 1), "'") THEN
	    'Do nothing

	ELIF EQUAL(LEFT$(element$[1], 3), "REM") THEN
	    'Do nothing

	ELSE
	    SELECT element$[1]
		CASE "USEC"
		    g_USE_C = 1

		CASE "PRINT"
		    Handle_Print(MID$(statement$, INSTR(statement$, "PRINT") + 5))

		CASE "INPUT"
		    Handle_Input(MID$(statement$, INSTR(statement$, "INPUT") + 5))

		CASE "FOR"
                    INCR g_LOOPCTR
		    Handle_For(MID$(statement$, INSTR(statement$, "FOR") + 3))

		CASE "NEXT"
		    WRITELN "}" TO g_CFILE
                    IF g_LOOPCTR > 0 THEN
                        DECR g_LOOPCTR
                        IF g_LOOPCTR > 0 THEN
                            WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE
                        END IF
                    END IF

		CASE "IF"
		    ' Check if THEN is available
		    g_IF_PARSE = 0
		    IF ISFALSE(INSTRREV(statement$, " THEN")) THEN
			PRINT NL$, "ERROR: missing THEN in IF statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE			
			' Translate function to C function
                        exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "IF") + 2, INSTRREV(statement$, " THEN") - (INSTR(statement$, "IF") + 2)))
			WRITELN "if(", exp$, "){" TO g_CFILE
			IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN
			    CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5))
			    g_IF_PARSE = 1
			END IF
		    ENDIF

		CASE "ELIF"
		    ' Check if THEN is available
		    g_IF_PARSE = 0
		    IF ISFALSE(INSTRREV(statement$, " THEN")) THEN
			PRINT NL$, "ERROR: missing THEN in ELIF statement at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate function to C function
                        exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "ELIF") + 4, INSTRREV(statement$, " THEN") - (INSTR(statement$, "ELIF") + 4)))
			WRITELN "} else if(", exp$, "){" TO g_CFILE
			IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN
			    CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5))
			    g_IF_PARSE = 1
			END IF
		    END IF

		CASE "ELSE"
		    ' Translate function to C function
		    g_IF_PARSE = 0
		    WRITELN "} else {" TO g_CFILE
		    IF LEN(CHOP$(MID$(statement$, INSTR(statement$, " ELSE") + 5))) > 0 THEN
			CALL Tokenize(MID$(statement$, INSTR(statement$, " ELSE") + 5))
			g_IF_PARSE = 1
		    END IF

		CASE "ENDIF"
		    WRITELN "}" TO g_CFILE

		CASE "WHILE"
                    INCR g_LOOPCTR
		    Handle_While(MID$(statement$, INSTR(statement$, "WHILE") + 5))

		CASE "WEND"
		    WRITELN "}" TO g_CFILE
                    IF g_LOOPCTR > 0 THEN
                        DECR g_LOOPCTR
                        IF g_LOOPCTR > 0 THEN
                            WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE
                        END IF
                    END IF

		CASE "BREAK"
                    ' Check argument
		    IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "BREAK") + 5)) NE 0 THEN
                         WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "BREAK") + 5), "-1; __b2c__break_flag = 1;" TO g_CFILE
                    END IF

		    WRITELN "break;" TO g_CFILE

		CASE "CONTINUE"
                    ' Check argument
		    IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) NE 0 THEN
                         WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "CONTINUE") + 8), "-1; __b2c__break_flag = 2;" TO g_CFILE
                    END IF
                    IF VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) > 1 THEN
		        WRITELN "break;" TO g_CFILE
                    ELSE
		        WRITELN "continue;" TO g_CFILE
                    END IF

		CASE "REPEAT"
                    INCR g_LOOPCTR
		    WRITELN "do{" TO g_CFILE

		CASE  "UNTIL"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty UNTIL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Convert to legal C code
                        exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "UNTIL") + 5) )
			WRITELN "} while(!(", exp$, "));" TO g_CFILE
                        IF g_LOOPCTR > 0 THEN
                            DECR g_LOOPCTR
                            IF g_LOOPCTR > 0 THEN
                                WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE
                            END IF
                        END IF
		    END IF

		CASE "LET"
		    Handle_Let(MID$(statement$, INSTR(statement$, "LET") + 3))

		CASE "SYSTEM"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty SYSTEM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			WRITELN "SYSTEM (", MID$(statement$, INSTR(statement$, "SYSTEM") + 6), ");" TO g_CFILE
		    END IF

		CASE "SLEEP"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty SLEEP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			WRITELN "usleep(", MID$(statement$, INSTR(statement$, "SLEEP") + 5), "*1000);" TO g_CFILE
		    END IF

		CASE "OPEN"
		    Handle_Open(MID$(statement$, INSTR(statement$, "OPEN") + 4))

		CASE "CLOSE"
		    ' Check argument
		    IF dim NE 3 THEN
			PRINT NL$, "ERROR: erroneous CLOSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			SELECT element$[2]
			    CASE "FILE"
				WRITELN "fclose(", element$[3], ");" TO g_CFILE
			    CASE "DIRECTORY"
				WRITELN "closedir(", element$[3], ");" TO g_CFILE
			    CASE "MEMORY"
				WRITELN element$[3], " = NULL;" TO g_CFILE
			    CASE "NETWORK";
			    CASE "SERVER"
				WRITELN "close(", element$[3], ");" TO g_CFILE
			END SELECT
		    END IF

		CASE "REWIND"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty REWIND at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			WRITELN "rewind(", element$[2], ");" TO g_CFILE
		    END IF

		CASE "MEMREWIND"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty MEMREWIND at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			WRITELN element$[2], " = (char*)__b2c_mem_", element$[2], ";" TO g_CFILE
		    END IF

		CASE "SEEK"
		    Handle_Seek(CHOP$(MID$(statement$, INSTR(statement$, "SEEK") + 4)))

		CASE "READLN"
		    Handle_Readln(CHOP$(MID$(statement$, INSTR(statement$, "READLN") + 6)))

		CASE "WRITELN"
		    Handle_Writeln(MID$(statement$, INSTR(statement$, "WRITELN") + 7))

		CASE "GETBYTE"
		    Handle_Getbyte(CHOP$(MID$(statement$, INSTR(statement$, "GETBYTE") + 7)))

		CASE "PUTBYTE"
		    Handle_Putbyte(CHOP$(MID$(statement$, INSTR(statement$, "PUTBYTE") + 7)))

		CASE "GETFILE"
		    Handle_Getfile(CHOP$(MID$(statement$, INSTR(statement$, "GETFILE") + 7)))

		CASE "GETLINE"
		    Handle_Getline(CHOP$(MID$(statement$, INSTR(statement$, "GETLINE") + 7)))

		CASE "PUTLINE"
		    Handle_Putline(MID$(statement$, INSTR(statement$, "PUTLINE") + 7))

		CASE "END"
		    IF dim > 1 THEN
			SELECT element$[2]
			    CASE "IF"
				WRITELN "}" TO g_CFILE
			    CASE "RECORD"
				IF LEN(g_FUNCNAME$) > 0 THEN
				    WRITELN "};" TO g_CFILE
				    WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { } ;" TO g_CFILE
				ELSE
				    WRITELN "};" TO g_HFILE
				    WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { } ;" TO g_HFILE
				END IF
				g_RECORDNAME$ = ""
				g_RECORDVAR$ = ""
				' Restore function name if GLOBAL was used
				IF LEN(g_RECORDCACHE$) > 0 THEN
				    g_FUNCNAME$ = g_RECORDCACHE$
				    g_RECORDCACHE$ = ""
				ENDIF
			    CASE "FUNCTION"
				Handle_Endfunction
			    CASE "SUB"
				Handle_Endsub
			    CASE "WITH"
				g_WITHVAR$ = ""
			    CASE "SELECT"
				IF g_SELECTVAR_CTR IS 0 THEN
				    PRINT NL$, "ERROR: invalid END SELECT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				    END 1
				ELSE
				    WRITELN "}" TO g_CFILE
				    g_SELECTVAR$[g_SELECTVAR_CTR] = ""
				    g_IN_CASE[g_SELECTVAR_CTR] = 0
				    g_CASE_FALL$ = ""
				    DECR g_SELECTVAR_CTR
				END IF
			    DEFAULT
				WRITELN "exit(", element$[2], ");" TO g_CFILE
			END SELECT
		    ELSE
			WRITELN "exit(EXIT_SUCCESS);" TO g_CFILE
		    END IF

		CASE "SUB"
		    Handle_SubFunc(MID$(statement$, INSTR(statement$, "SUB") + 3))

		CASE "ENDSUB"
		    Handle_Endsub

		CASE "ENDWITH"
		    g_WITHVAR$ = ""

		CASE "ENDSELECT"
		    IF g_SELECTVAR_CTR IS 0 THEN
			PRINT NL$, "ERROR: invalid END SELECT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			WRITELN "}" TO g_CFILE
			g_SELECTVAR$[g_SELECTVAR_CTR] = ""
			g_IN_CASE[g_SELECTVAR_CTR] = 0
			g_CASE_FALL$ = ""
			DECR g_SELECTVAR_CTR
		    END IF

		CASE "CALL"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty CALL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			exp$ = MID$(statement$, INSTR(statement$, "CALL ") + 5)
			IF INSTR(statement$, " TO ") THEN
			    IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN
				WRITELN MID$(exp$, INSTR(exp$, " TO ") + 4), " = realloc(", MID$(exp$, INSTR(exp$, " TO ") + 4), ", (strlen(", MID$(exp$, 1, INSTR(exp$, " TO ") - 1), ")+1)*sizeof(char));" TO g_CFILE
				WRITELN "strcpy(", MID$(exp$, INSTR(exp$, " TO ") + 4), "," TO g_CFILE
			    ELSE
				WRITELN MID$(exp$, INSTR(exp$, " TO") + 3), "=" TO g_CFILE
			    END IF
			    IF INSTR(exp$, "(") THEN
				WRITELN MID$(exp$, 1, INSTR(exp$, " TO ") - 1) TO g_CFILE
			    ELSE
				WRITELN MID$(exp$, 1, INSTR(exp$, " TO ") - 1), "()" TO g_CFILE
			    END IF
			    IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN
				WRITELN ");" TO g_CFILE
			    ELSE
				WRITELN ";" TO g_CFILE
			    END IF
			ELSE
			    IF INSTR(exp$, "(") THEN
				WRITELN exp$, ";" TO g_CFILE
			    ELSE
				WRITELN exp$, "();" TO g_CFILE
			    END IF
			END IF
		    END IF

		CASE "FUNCTION"
		    Handle_SubFunc(MID$(statement$, INSTR(statement$, "FUNCTION") + 8))

		CASE "ENDFUNCTION"
		    Handle_Endfunction

		CASE "RETURN"
		    Handle_Return(MID$(statement$, INSTR(statement$, "RETURN") + 6))

		CASE "IMPORT"
		    Handle_Import(MID$(statement$, INSTR(statement$, "IMPORT") + 6))

		CASE "DECLARE"
		    Handle_Declare(MID$(statement$, INSTR(statement$, "DECLARE") + 7))

		CASE "GLOBAL"
		    Handle_Declare(MID$(statement$, INSTR(statement$, "GLOBAL") + 6))

		CASE "LOCAL"
		    Handle_Local(MID$(statement$, INSTR(statement$, "LOCAL") + 5))

		CASE "DATA"
		    Handle_Data(MID$(statement$, INSTR(statement$, "DATA") + 4))

		CASE "RESTORE"
		    WRITELN "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" TO g_CFILE
		    WRITELN "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" TO g_CFILE

		CASE "READ"
		    Handle_Read(CHOP$(MID$(statement$, INSTR(statement$, "READ") + 4)))

		CASE "PUSH"
		    Handle_Push(CHOP$(MID$(statement$, INSTR(statement$, "PUSH") + 4)))

		CASE "PULL"
		    Handle_Pull(CHOP$(MID$(statement$, INSTR(statement$, "PULL") + 4)))

		CASE "SEED"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty DATA at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			WRITELN "srandom((unsigned int)", element$[2], ");" TO g_CFILE
		    END IF

		CASE "DEF"
		    Handle_Deffn(CHOP$(MID$(statement$, INSTR(statement$, "DEF") + 3)))

		CASE "CONST"
		    Handle_Const(CHOP$(MID$(statement$, INSTR(statement$, "CONST") + 5)))

		CASE "INCLUDE"
		    ' Get rid of doublequotes if they are there
		    inc$ = REPLACE$((CHOP$(MID$(statement$, INSTR(statement$, " ") + 1))), CHR$(34), "")
		    ' See if there are arguments
		    IF INSTR(inc$, ",") THEN
			SPLIT MID$(inc$, INSTR(inc$, ",")+1) BY "," TO element$ SIZE size
			FOR i = 1 TO size
			    element$[i] = REPLACE$(element$[i], g_STRINGSIGN$, "")
			NEXT
			inc$ = MID$(inc$, 1, INSTR(inc$, ",")-1)
		    ELSE
			to_parse = 2
		    END IF

		    ' Check argument
		    IF NOT(FILEEXISTS(inc$)) OR dim EQ 1 OR FILETYPE(inc$) != 1 THEN
			PRINT NL$, "ERROR: missing file '", inc$, "' for INCLUDE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Start walking through program
			copy_counter = g_COUNTER
			g_COUNTER = 1
			' Assign new file
			copy_curfile$ = g_CURFILE$
			' Get rid of absolute path
			g_CURFILE$ = MID$(inc$, INSTRREV(inc$, "/") + 1)
			OPEN inc$ FOR READING AS newfile

			WHILE NOT(ENDFILE(newfile)) DO
			    PRINT "\rStarting conversion... ", g_COUNTER, " ";
			    READLN txt$ FROM newfile
			    ' See if we need to enable flag
			    IF size > 0 THEN
				FOR i = 1 TO size
				    IF ( to_parse = 0 AND REGEX(CHOP$(MID$(txt$, INSTR(txt$, " "))), CONCAT$("^", CHOP$(element$[i]))) AND REGEX(txt$, "SUB|FUNCTION") ) OR REGEX(txt$, "INCLUDE$") THEN
					to_parse = 1
					BREAK
				    END IF
				NEXT
			    END IF
			    ' Line is not empty?
			    IF NOT(ENDFILE(newfile)) AND LEN(txt$) > 0 AND to_parse > 0 THEN
				IF EQUAL(RIGHT$(txt$, 2), CONCAT$(" ", CHR$(92))) AND NOT(EQUAL(LEFT$(txt$, 3), "REM")) AND NOT(EQUAL(LEFT$(txt$, 1), CHR$(39))) THEN
				    total$ = CONCAT$(total$, LEFT$(txt$, LEN(txt$)-2))
				ELSE
				    WRITELN "/* noparse ", inc$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE
				    WRITELN "/* noparse ", inc$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE
				    total$ = CHOP$(CONCAT$(total$, txt$))
				    IF NOT(EQUAL(LEFT$(total$, 3), "REM")) AND NOT(EQUAL( LEFT$(total$, 1), CHR$(39) )) THEN
					CALL Tokenize(total$)
				    END IF
				    LET total$ = ""
				END IF
			    ENDIF
			    ' See if we need to stop parsing
			    IF to_parse = 1 AND INSTR(txt$, "END") AND REGEX(txt$, "SUB|FUNCTION") THEN to_parse = 0
			    ' Increase line number
			    INCR g_COUNTER
			WEND
			CLOSE FILE newfile

			' Restore original counter
			g_COUNTER = copy_counter
			' Restore original file
			g_CURFILE$ = copy_curfile$
		    END IF

		CASE "POKE"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty POKE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			exp$ = MID$(statement$, INSTR(statement$, "POKE") + 4)
			WRITELN "if (!__b2c__trap){__b2c__memory__check((char*)", MID$(exp$, 1, INSTR(exp$, ",")-1), "); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} }" TO g_CFILE
			WRITELN "*(", g_OPTION_MEMTYPE$, "*)(", MID$(exp$, 1, INSTR(exp$, ",")-1), ") = ( ", g_OPTION_MEMTYPE$, ")", MID$(exp$, INSTR(exp$, ",")+1), ";" TO g_CFILE
		    END IF

		CASE "RESIZE"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty RESIZE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Resolve this with C macro because of casting to (char)
			exp$ = MID$(statement$, INSTR(statement$, "RESIZE") + 6)
			WRITELN MID$(exp$, 1, INSTR(exp$, ",") - 1), " = (long)RESIZE(", exp$, ");" TO g_CFILE
		    END IF

		CASE "COPY"
		    Handle_Copy(MID$(statement$, INSTR(statement$, "COPY") + 4))

		CASE "DELETE"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty DELETE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate to C function
			IF EQUAL(element$[2], "FILE") THEN
			    WRITELN "if (unlink(", MID$(statement$, INSTR(statement$, " FILE ") + 6), ")==-1){if(!__b2c__trap){ERROR = 7;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			ELIF EQUAL(element$[2], "DIRECTORY") THEN
			    WRITELN "if (rmdir(", MID$(statement$, INSTR(statement$, " DIRECTORY ") + 11), ") == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			ELSE
			    PRINT NL$, "ERROR: erronuous argument for DELETE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			    END 1
			END IF
		    END IF

		CASE "RENAME"
		    Handle_Rename(MID$(statement$, INSTR(statement$, "RENAME") + 6))

		CASE "MAKEDIR"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty MAKEDIR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate to C function
			WRITELN "if(__b2c__makedir(", MID$(statement$, INSTR(statement$, "MAKEDIR") + 7), ") != 0){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		    END IF

		CASE "CHANGEDIR"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty CHANGEDIR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate to C function
			WRITELN "if(chdir(", MID$(statement$, INSTR(statement$, "CHANGEDIR") + 9), ") == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
		    END IF

		CASE "FREE"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty FREE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate to C function
			IF REGEX(element$[2], "\\(.*\\)") THEN
			    exp$ = MID$(element$[2], INSTR(element$[2], " ")+1)
			    IF INSTR(exp$, g_STRINGSIGN$) THEN
				WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1)," != NULL) {free(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value);" TO g_CFILE
				WRITELN " __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value = NULL; __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(", MID$(element$[2], INSTR(element$[2], "(")+1), "; }" TO g_CFILE
			    ELSE
				WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1)," != NULL) {__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value = 0;" TO g_CFILE
				WRITELN "__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(", MID$(element$[2], INSTR(element$[2], "(")+1), ";}" TO g_CFILE
			    ENDIF
			ELSE
			    WRITELN "if(!__b2c__trap){__b2c__memory__check((char *)", element$[2], ");" TO g_CFILE
			    WRITELN "if(ERROR) {if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } free((void*)", element$[2], ");" TO g_CFILE
			END IF
		    END IF

		CASE "GOTO"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty GOTO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate to C label
			WRITELN "goto ", element$[2], ";" TO g_CFILE
		    END IF

		CASE "LABEL"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty LABEL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Translate to C label
			WRITELN element$[2], ":" TO g_CFILE
			WRITELN ";" TO g_CFILE
		    END IF

		CASE "TRAP"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty TRAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			IF EQUAL(element$[2], "SYSTEM") THEN
			    WRITELN "/* Error catching is enabled */" TO g_CFILE
			    WRITELN "__b2c__trap = 1;" TO g_CFILE
			    WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE
			    WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE
			    WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE
			    WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE
			ELIF EQUAL(element$[2], "LOCAL") THEN
			    WRITELN "/* Error catching is disabled */" TO g_CFILE
			    WRITELN "__b2c__trap = 0;" TO g_CFILE
			    WRITELN "signal(SIGILL, SIG_DFL);" TO g_CFILE
			    WRITELN "signal(SIGABRT, SIG_DFL);" TO g_CFILE
			    WRITELN "signal(SIGFPE, SIG_DFL);" TO g_CFILE
			    WRITELN "signal(SIGSEGV, SIG_DFL);" TO g_CFILE
			ELSE
			    PRINT NL$, "ERROR: invalid argument for TRAP at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			    END 1
			END IF
		    END IF

		CASE "CATCH"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty CATCH at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELIF EQUAL(element$[2], "GOTO") THEN
			WRITELN "__b2c__catch_set = 1;" TO g_CFILE
			g_CATCHGOTO$ = element$[3]
		    ELIF EQUAL(element$[2], "RESET") THEN
			WRITELN "__b2c__catch_set = 0;" TO g_CFILE
			g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
		    ELSE
			PRINT NL$, "ERROR: CATCH without GOTO or RESET at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    END IF

		CASE "RESUME"
		    WRITELN "longjmp(__b2c__jump, 1);" TO g_CFILE

		CASE "CLEAR"
		    WRITELN "fprintf(stdout,\"\\033[2J\"); fprintf(stdout,\"\\033[0;0f\");fflush(stdout);" TO g_CFILE

		CASE "COLOR"
		    Handle_Color(CHOP$(MID$(statement$, INSTR(statement$, "COLOR") + 5)))

		CASE "GOTOXY"
		    Handle_Gotoxy(CHOP$(MID$(statement$, INSTR(statement$, "GOTOXY") + 6)))

		CASE "RECEIVE"
		    Handle_Receive(CHOP$(MID$(statement$, INSTR(statement$, "RECEIVE") + 7)))

		CASE "SEND"
		    Handle_Send(MID$(statement$, INSTR(statement$, "SEND") + 4))

		CASE "RECORD"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty RECORD at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN
			PRINT NL$, "ERROR: cannot define a record within a record!"
			END 1
		    ELSE
			' Translate to C typedef struct
			IF ISTRUE(LEN(g_FUNCNAME$)) THEN
			    g_RECORDNAME$ = CONCAT$("RECORD_", g_FUNCNAME$, "_", STR$(g_COUNTER))
			    WRITELN "struct ", g_RECORDNAME$, "{" TO g_CFILE
			ELSE
			    g_RECORDNAME$ = CONCAT$("RECORD_", STR$(g_COUNTER))
			    WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE
			END IF
			g_RECORDVAR$ = element$[2]
		    END IF

		CASE "WITH"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty WITH at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN
			PRINT NL$, "ERROR: cannot define a WITH within a WITH!"
			END 1
		    ELSE
			g_WITHVAR$ = element$[2]
		    END IF

		CASE "SPLIT"
		    Handle_Split(MID$(statement$, INSTR(statement$, "SPLIT") + 5))

		CASE "SELECT"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty SELECT at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			INCR g_SELECTVAR_CTR
			g_SELECTVAR$[g_SELECTVAR_CTR] = MID$(statement$, INSTR(statement$, "SELECT") + 6)
			g_IN_CASE[g_SELECTVAR_CTR] = 0
			g_CASE_FALL$ = ""
		    END IF

		CASE "CASE"
		   ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty CASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN
			    IF INSTR(g_SELECTVAR$[g_SELECTVAR_CTR], g_STRINGSIGN$) THEN
				IF EQUAL(RIGHT$(statement$, 1), ";") THEN
				    exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
				    g_CASE_FALL$ = CONCAT$("|| !strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", LEFT$(exp$, LEN(exp$)-1), ") ", g_CASE_FALL$)
				ELSE
				    WRITELN "} else if (!strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE
				    g_CASE_FALL$ = ""
				END IF
			    ELSE
				IF EQUAL(RIGHT$(statement$, 1), ";") THEN
				    exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
				    g_CASE_FALL$ = CONCAT$("|| ", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", LEFT$(exp$, LEN(exp$)-1), ")", g_CASE_FALL$)
				ELSE
				    WRITELN "} else if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE
				    g_CASE_FALL$ = ""
				END IF
			    END IF
			ELSE
			    IF INSTR(g_SELECTVAR$[g_SELECTVAR_CTR], g_STRINGSIGN$) THEN
				IF EQUAL(RIGHT$(statement$, 1), ";") THEN
				    exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
				    g_CASE_FALL$ = CONCAT$("|| !strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", LEFT$(exp$, LEN(exp$)-1), ") ", g_CASE_FALL$)
				ELSE
				    WRITELN "if (!strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4),") ", g_CASE_FALL$, "){" TO g_CFILE
				    g_IN_CASE[g_SELECTVAR_CTR] = 1
				    g_CASE_FALL$ = ""
				END IF
			    ELSE
				IF EQUAL(RIGHT$(statement$, 1), ";") THEN
				    exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
				    g_CASE_FALL$ = CONCAT$("|| ", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", LEFT$(exp$, LEN(exp$)-1), ")", g_CASE_FALL$)
				ELSE
				    WRITELN "if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE
				    g_IN_CASE[g_SELECTVAR_CTR] = 1
				    g_CASE_FALL$ = ""
				END IF
			    END IF
			END IF
		    END IF

		CASE "DEFAULT"
		    IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN
			WRITELN "} else {" TO g_CFILE
		    ELSE
			PRINT NL$, "ERROR: cannot use DEFAULT without previous CASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    END IF
		    g_IN_CASE[g_SELECTVAR_CTR] = 0
		    g_CASE_FALL$ = ""

		CASE "SETENVIRON"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty SETENVIRON at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Resolve this with C macro
			WRITELN "SETENVIRON(", MID$(statement$, INSTR(statement$, "SETENVIRON") + 10), ");" TO g_CFILE
		    END IF

		CASE "SORT"
		    Handle_Sort(CHOP$(MID$(statement$, INSTR(statement$, "SORT") + 4)))

		CASE "STOP"
		    WRITELN "kill(getpid(), SIGSTOP);" TO g_CFILE

		CASE "TRACE"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty TRACE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			IF EQUAL(element$[2], "ON") THEN g_TRACE = 1
			ELIF EQUAL(element$[2], "OFF") THEN g_TRACE =0
		    ENDIF

		CASE "OPTION"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty OPTION at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			IF EQUAL(element$[2], "BASE") AND dim IS 3 THEN
			    IF REGEX(element$[3], "[0-9]") THEN
				g_OPTION_BASE = VAL(element$[3])
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION BASE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
			ELIF EQUAL(element$[2], "COMPARE") AND dim IS 3 THEN
			    IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
			        WRITELN "__b2c__option_compare = ", element$[3], ";" TO g_CFILE
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION COMPARE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
			ELIF EQUAL(element$[2], "SOCKET") AND dim IS 3 THEN
			    IF REGEX(element$[3], "[0-9]") THEN
				g_OPTION_SOCKET = VAL(element$[3])
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION SOCKET at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
                        ELIF EQUAL(element$[2], "MEMSTREAM") AND dim IS 3 THEN
			    IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
			        WRITELN "__b2c__option_memstream = ", element$[3], ";" TO g_CFILE
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION MEMSTREAM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
			ELIF EQUAL(element$[2], "MEMTYPE") AND dim IS 3 THEN
			    IF REGEX(statement$, ".*short.*") THEN
                                WRITELN "__b2c__memtype = 2;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "short"
			    ELIF REGEX(statement$, ".*int.*") THEN
                                WRITELN "__b2c__memtype = 3;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "int"
			    ELIF REGEX(statement$, ".*long.*|.*NUMBER.*") THEN
                                WRITELN "__b2c__memtype = 4;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "long"
			    ELIF REGEX(statement$, ".*float.*") THEN
                                WRITELN "__b2c__memtype = 5;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "float"
			    ELIF REGEX(statement$, ".*double.*|.*FLOATING.*") THEN
                                WRITELN "__b2c__memtype = 6;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "double"
			    ELIF REGEX(statement$, ".*void.*|.*char\\*.*|.*STRING.*") THEN
                                WRITELN "__b2c__memtype = 7;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "char*"
			    ELIF REGEX(statement$, ".*char.*") THEN
                                WRITELN "__b2c__memtype = 1;" TO g_CFILE
				g_OPTION_MEMTYPE$ = "char"
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION MEMTYPE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
                       ELIF EQUAL(element$[2], "COLLAPSE") AND dim IS 3 THEN
			    IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
			        WRITELN "__b2c__collapse = ", element$[3], ";" TO g_CFILE
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION COLLAPSE at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
                        ELIF EQUAL(element$[2], "INTERNATIONAL") AND dim IS 3 THEN
			    IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
				WRITELN "#include <libintl.h>" TO g_HFILE
				WRITELN "#include <locale.h>" TO g_HFILE
				WRITELN "setlocale(LC_ALL, \"\");" TO g_CFILE
				WRITELN "if(bindtextdomain(\"", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), "\",\"/usr/share/locale\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
				WRITELN "if(textdomain(\"", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), "\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			    ELSE
				PRINT NL$, "ERROR: invalid argument to OPTION INTERNATIONAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
				END 1
			    END IF
			ELSE
			    PRINT NL$, "ERROR: argument to OPTION at line ", g_COUNTER, " in file '", g_CURFILE$, "' not recognized!"
			    END 1
			END IF
		    END IF

		CASE "PROTO"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty PROTO at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			exp$ = MID$(REPLACE$(statement$, CHR$(34), ""), INSTR(statement$, "PROTO") + 5)
			' Check if ALIAS is there
			IF INSTR(exp$, " ALIAS ") THEN
			    WRITELN "#define ", MID$(exp$, INSTR(exp$, " ALIAS ") + 7), " ", MID$(exp$, 1, INSTR(exp$, " ALIAS ")) TO g_HFILE
			    g_IMPORTED$ = CONCAT$(MID$(exp$, INSTR(exp$, " ALIAS ") + 7), " ", g_IMPORTED$)
			    g_IMPORTED$ = CONCAT$(MID$(exp$, 1, INSTR(exp$, " ALIAS ")), " ", g_IMPORTED$)
			ELSE
			    g_IMPORTED$ = CONCAT$(REPLACE$(exp$, ",", " "), " ", g_IMPORTED$)
			END IF
		    END IF

		CASE "INCR"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty INC at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Walk through commas
			SPLIT CHOP$(MID$(statement$, INSTR(statement$, "INCR") + 4)) BY "," TO sym$ SIZE dim
			IF dim IS 1 THEN
			    WRITELN sym$[1], " = ", sym$[1], " + 1;" TO g_CFILE
			ELSE
			    WRITELN sym$[1], " = ", sym$[1], " + (", CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)), ");" TO g_CFILE
			END IF
		    END IF

		CASE "DECR"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty INC at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Walk through commas
			SPLIT CHOP$(MID$(statement$, INSTR(statement$, "DECR") + 4)) BY "," TO sym$ SIZE dim
			IF dim IS 1 THEN
			    WRITELN sym$[1], " = ", sym$[1], " - 1;" TO g_CFILE
			ELSE
			    WRITELN sym$[1], " = ", sym$[1], " - (", CHOP$(MID$(statement$, INSTR(statement$, ",") + 1)), ");" TO g_CFILE
			END IF
		    END IF

		CASE "ALARM"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Walk through commas
			SPLIT CHOP$(MID$(statement$, INSTR(statement$, "ALARM") + 5)) BY "," TO sym$ SIZE dim
			IF dim IS 2 THEN
			    WRITELN "signal(SIGALRM, (void*)", sym$[1], ");" TO g_CFILE
			    WRITELN "alarm(", sym$[2], ");" TO g_CFILE
			ELSE
			    PRINT NL$, "ERROR: missing argument in ALARM at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			    END 1
			END IF
		    END IF

		CASE "CURSOR"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty CURSOR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			IF EQUAL(element$[2], "ON") THEN WRITELN "fprintf(stdout,\"\\033[?25h\"); fflush(stdout);" TO g_CFILE
			ELIF EQUAL(element$[2], "OFF") THEN WRITELN "fprintf(stdout,\"\\033[?25l\"); fflush(stdout);" TO g_CFILE
		    ENDIF

		CASE "ALIAS"
		    Handle_Alias(CHOP$(MID$(statement$, INSTR(statement$, "ALIAS") + 5)))

		CASE "LOOKUP"
		    Handle_Lookup(CHOP$(MID$(statement$, INSTR(statement$, "LOOKUP") + 6)))

		CASE "RELATE"
		    Handle_Relate(CHOP$(MID$(statement$, INSTR(statement$, "RELATE") + 6)))

		CASE "TEXTDOMAIN"
		    ' Check argument
		    IF dim EQ 1 THEN
			PRINT NL$, "ERROR: empty TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			END 1
		    ELSE
			' Walk through commas
			SPLIT CHOP$(MID$(statement$, INSTR(statement$, "TEXTDOMAIN") + 10)) BY "," TO sym$ SIZE dim
			IF dim IS 2 THEN
			    WRITELN "if(bindtextdomain(", sym$[1], ",", sym$[2], ")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			    WRITELN "if(textdomain(", sym$[1], ")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
			ELSE
			    PRINT NL$, "ERROR: missing argument in TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
			    END 1
			END IF
		    END IF

		DEFAULT
		    ' Check on imported symbols first
		    IF INSTR(element$[1], "(") THEN element$[1] = LEFT$(element$[1], INSTR(element$[1], "(") - 1)

		    SPLIT CHOP$(g_IMPORTED$) BY " " TO sym$ SIZE dim
		    found = FALSE

		    FOR i = 1 TO dim
			IF EQUAL(sym$[i], element$[1]) THEN
			    IF REGEX(statement$, "\\(.*\\)") THEN WRITELN statement$, ";" TO g_CFILE
			    ELSE WRITELN statement$, "();" TO g_CFILE
			    found = TRUE
			    BREAK
			END IF
		    NEXT
		    ' Not an imported symbol? Check if assignment
		    IF NOT(found) THEN Handle_Let(statement$)
	    END SELECT
	END IF
    END IF

END SUB

'----------------------------------------------------------------------------------------------

SUB Tokenize (STRING current$)

    LOCAL dim, i, is_string, is_escaped
    LOCAL token$

    ' Initialize parser
    is_string = FALSE
    is_escaped = FALSE
    token$ = ""

    ' See if there are colons
    FOR i = 1 TO LEN(current$)
	IF EQUAL(MID$(current$, i, 5), "INTL$") THEN
	    IF ISFALSE(is_string) THEN
		token$ = CONCAT$(token$, "gettext")
		INCR i, 5
	    END IF
	ELIF EQUAL(MID$(current$, i, 5), "NNTL$") THEN
	    IF ISFALSE(is_string) THEN
		token$ = CONCAT$(token$, "ngettext")
		INCR i, 5
	    END IF
	END IF
	SELECT MID$(current$, i, 1)
	    ' Separator
	    CASE ":"
		IF ISFALSE(is_string) THEN
		    token$ = CONCAT$(token$, CHR$(10))
		ELSE
		    token$ = CONCAT$(token$, ":")
		END IF
	    ' String symbol
	    CASE "$"
		IF ISFALSE(is_string) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN
		    token$ = CONCAT$(token$, g_STRINGSIGN$)
		    is_escaped = FALSE
		ELSE
		    token$ = CONCAT$(token$, "$")
		END IF
	    ' Escape symbol
	    CASE CHR$(92)
		token$ = CONCAT$(token$, CHR$(92))
		is_escaped = NOT(is_escaped)
	    ' Quote symbol
	    CASE CHR$(34)
		token$ = CONCAT$(token$, CHR$(34))
		IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
		is_escaped = FALSE
	    DEFAULT
		token$ = CONCAT$(token$, MID$(current$, i, 1))
		is_escaped = FALSE
	END SELECT
    NEXT
    ' Split into separate statements
    SPLIT token$ BY CHR$(10) TO element$ SIZE dim
    ' Start parsing
    FOR i = 1 TO dim
	Parse_Line(CHOP$(element$[i]))
    NEXT

END SUB

'----------------------------------------------------------------------------------------------

FUNCTION Parse_Equation$(STRING current$)

    LOCAL dim, i, j, is_string, is_escaped, is_equation, opctr
    LOCAL token$, term$, eq$, total$, type$
    LOCAL logop$[32]

    ' Initialize parser
    is_string = FALSE
    is_escaped = FALSE
    opctr = 1

    ' First split into separate chunks OR/AND
    FOR i = 1 TO LEN(current$)
        IF EQUAL(MID$(current$, i, 5), " AND ") THEN
            IF ISFALSE(is_string) THEN
		token$ = CONCAT$(token$, CHR$(10))
                logop$[opctr] = " AND "
                INCR opctr : INCR i, 4
            ELSE
		token$ = CONCAT$(token$, " ")
            END IF
        ELIF EQUAL(MID$(current$, i, 4), " OR ") THEN
            IF ISFALSE(is_string) THEN
		token$ = CONCAT$(token$, CHR$(10))
                logop$[opctr] = " OR "
                INCR opctr : INCR i, 3
            ELSE
		token$ = CONCAT$(token$, " ")
            END IF
        ELIF EQUAL(MID$(current$, i, 1), CHR$(92)) THEN
	    token$ = CONCAT$(token$, CHR$(92))
	    is_escaped = NOT(is_escaped)
        ELIF EQUAL(MID$(current$, i, 1), CHR$(34)) THEN
	    token$ = CONCAT$(token$, CHR$(34))
	    IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
	    is_escaped = FALSE
	ELSE
	    token$ = CONCAT$(token$, MID$(current$, i, 1))
	    is_escaped = FALSE
	END IF
    NEXT
    logop$[opctr] = ""
    opctr = 1

    ' Split into separate chunks
    SPLIT token$ BY CHR$(10) TO element$ SIZE dim

    ' Start parsing
    FOR j = 1 TO dim

        eq$ = "!"
        token$ = ""

        ' Check if this is a string
        IF INSTR(element$[j], "(") THEN
            type$ = MID$(element$[j], 1, INSTR(element$[j], "("))
        ELSE
            type$ = element$[j]
        END IF

        ' See if there are equal signs
        FOR i = 1 TO LEN(element$[j])

	    SELECT MID$(element$[j], i, 1)
	        ' Separator
	        CASE "="
		    IF ISFALSE(is_string) THEN
                        IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN
                            term$ = token$
                            token$ = ""
                        ELIF NOT(is_equation) THEN
		            token$ = CONCAT$(token$, "==")
                        ELSE
		            token$ = CONCAT$(token$, "=")
                            is_equation = 0
                        END IF
		    ELSE
		        token$ = CONCAT$(token$, "=")
		    END IF
                ' Negation
	        CASE "!"
		    IF ISFALSE(is_string) THEN
                        IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN
                            eq$ = ""
                        ELIF NOT(is_equation) THEN
		            token$ = CONCAT$(token$, "!=")
                            INCR i
                        ELSE
		            token$ = CONCAT$(token$, "!")
                            is_equation = 0
                        END IF
                    ELSE
		        token$ = CONCAT$(token$, "!")
                    END IF
	        ' Comparison symbols
	        CASE "<"
		    token$ = CONCAT$(token$, "<")
                    is_equation = 1
	        CASE ">"
		    token$ = CONCAT$(token$, ">")
                    is_equation = 1
	        CASE "#"
		    token$ = CONCAT$(token$, "#")
                    is_equation = 1
	        ' Escape symbol
	        CASE CHR$(92)
		    token$ = CONCAT$(token$, CHR$(92))
		    is_escaped = NOT(is_escaped)
	        ' Quote symbol
	        CASE CHR$(34)
		    token$ = CONCAT$(token$, CHR$(34))
		    IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
		    is_escaped = FALSE
	        DEFAULT
		    token$ = CONCAT$(token$, MID$(element$[j], i, 1))
		    is_escaped = FALSE
	    END SELECT
        NEXT

        ' Construct string equation
        IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN token$ = CONCAT$("((__b2c__option_compare == 0) ? ", eq$, "strcmp(", term$, ",", token$, ") : ", eq$, "strcasecmp(", term$, ",", token$, "))")

        total$ = CONCAT$(total$, token$)

        ' Restore logical operator
        total$ = CONCAT$(total$, logop$[opctr])
        INCR opctr
    NEXT

    RETURN total$

END FUNCTION

'----------------------------------------------------------------------------------------------

SUB Download_File(STRING name$)

    LOCAL total$, dat$
    LOCAL length, mynet
    LOCAL baconfile TYPE FILE*

    PRINT "Fetching file... ";

    OPEN CONCAT$(LEFT$(name$, INSTR(name$, "/")-1), ":80") FOR NETWORK AS mynet
    SEND CONCAT$("GET /", MID$(name$, INSTR(name$, "/")+1), " HTTP/1.1\r\nHost: ", LEFT$(name$, INSTR(name$, "/")-1), "\r\n\r\n") TO mynet

    RECEIVE dat$ FROM mynet

    ' Get the filesize from the HTTP header
    IF NOT(INSTR(dat$, "Content-Length:")) THEN
        PRINT "ERROR: file not found! Check URL and try again."
        END 1
    END IF

    dat$ = MID$(dat$, INSTR(dat$, "Content-Length:")+15)
    length = VAL(LEFT$(dat$, INSTR(dat$, NL$)))

    ' As long as there is data, get it
    WHILE WAIT(mynet, 1000)
	total$ = CONCAT$(total$, dat$)
	RECEIVE dat$ FROM mynet
        IF LEN(dat$) = 0 THEN BREAK
    WEND
    total$ = CONCAT$(total$, dat$)

    CLOSE NETWORK mynet

    ' Write to file
    OPEN MID$(name$, INSTR(name$, "/")+1) FOR WRITING AS baconfile
	WRITELN MID$(total$, INSTR(total$, "\r\n\r\n")+4) TO baconfile
    CLOSE FILE baconfile

    IF FILELEN(MID$(name$, INSTR(name$, "/")+1)) != length+1 THEN
        PRINT "ERROR: file could not be downloaded. Try again later."
        END 1
    END IF

    PRINT "done."

END SUB

'----------------------------------------------------------------------------------------------
'
' Main program
'
'----------------------------------------------------------------------------------------------

' Default BACON settings
LET g_MAX_DIGITS = 32

' Maximum of internal buffers needed for string processing
LET g_MAX_BUFFERS = 32

' This is the size for static buffers like fgets, read etc.
LET g_BUFFER_SIZE = 512

' Maximum RETURN buffers
LET g_MAX_RBUFFERS = 32

LET g_NO_COMPILE = 0
LET g_TMP_PRESERVE = 0
LET g_USE_C = 0
LET g_MAX_BACKLOG = 4
LET g_CPP = 0
LET g_SHEBANG = FALSE
LET g_XGETTEXT = 0

g_TEMPDIR$ = "."
g_CCNAME$ = "cc"
g_CCFLAGS$ = ""
g_INCFILES$ = ""
g_INCLUDE_FILES$ = ""
LET g_TRACE = 0
LET g_OPTION_BASE = 0
LET g_OPTION_SOCKET = 5
LET g_OPTION_MEMTYPE$ = "char"
LET g_IF_PARSE = 0

' Some global declarations
g_CURFILE$ = ""
g_FUNCNAME$ = ""
g_FUNCTYPE$ = ""
g_PROTOTYPE$ = ""
g_TMP_FILES$ = ""
g_LOCALSTRINGS$ = ""
g_STRINGARRAYS$ = ""
g_STRINGARGS$ = ""
g_BINEXT$ = ""
g_RECORDCACHE$ = ""
LET g_LOOPCTR = 0
g_ERRORTXT$ = ""

' Always create a final label
g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"

' Records
g_RECORDNAME$ = ""
g_RECORDVAR$ = ""
g_WITHVAR$ = ""

' Select/Case currently 16 levels deep
DECLARE g_SELECTVAR$[16]
DECLARE g_IN_CASE[16]
g_SELECTVAR_CTR = 0

' Relate currently 256
DECLARE g_RELATE$[256]
g_RELATE_CTR = 0

SPLIT CHOP$(ARGUMENT$) BY " " TO args$ SIZE amount

IF amount < 2 THEN
    PRINT "ERROR: no filename? Run with '-h' to see usage."
    END
ENDIF

i = 1

WHILE i <= amount DO

    SELECT LEFT$(args$[i], 2)

	' Compiler option
	CASE "-c"
	    INCR i
	    IF LEN(args$[i]) > 0 THEN g_CCNAME$ = args$[i]

	' Include option
	CASE "-i"
	    INCR i
	    IF NOT(FILEEXISTS(args$[i])) AND NOT(FILEEXISTS(CONCAT$("/usr/include/", args$[i]))) THEN
		PRINT NL$, "ERROR: included C header file from -i option not found!"
		END 1
	    END IF
	    IF LEN(args$[i]) > 0 THEN
		IF NOT(FILEEXISTS(CONCAT$("/usr/include/", args$[i]))) THEN
		    g_INCFILES$ = CONCAT$("#include \"", args$[i], "\"", NL$, g_INCFILES$)
		ELSE
		    g_INCFILES$ = CONCAT$("#include <", args$[i], ">", NL$, g_INCFILES$)
		END IF
	    END IF

	' Library flags
	CASE "-l"
	    IF LEN(args$[i]) > 2 THEN
		g_LDFLAGS$ = CONCAT$(g_LDFLAGS$, " -l", MID$(args$[i], 3))
	    ELSE
		INCR i
		IF i <= amount THEN g_LDFLAGS$ = CONCAT$(g_LDFLAGS$, " -l", args$[i])
	    END IF

	' Compiler flags
	CASE "-o"
	    INCR i
	    IF LEN(args$[i]) > 0 THEN g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " ", args$[i])

	' Temporary directory
	CASE "-d"
	    INCR i
	    IF LEN(args$[i]) > 0 THEN
		IF NOT(FILEEXISTS(args$[i])) THEN MAKEDIR args$[i]
		g_TEMPDIR$ = args$[i]
	    END IF

	' Help option
	CASE "-h";
	CASE "-?"
	    PRINT NL$, "USAGE: bacon [options] program[.bac]"
	    PRINT NL$, "OPTIONS:"
	    PRINT NL$, " -c <compiler>", TAB$(1), "Compiler to use (default: ", g_CCNAME$, ")"
	    PRINT " -l <flags>", TAB$(1), "Pass libraries to linker"
	    PRINT " -o <options>", TAB$(1), "Pass compiler options"
	    PRINT " -i <include>", TAB$(1), "Add include file to C code"
	    PRINT " -d <tmpdir>", TAB$(1), "Temporary directory (default: ", g_TEMPDIR$, ")"
	    PRINT " -x ", TAB$(2), "Extract gettext strings"
	    PRINT " -f ", TAB$(2), "Create Shared Object"
	    PRINT " -n ", TAB$(2), "Do not compile, only convert"
	    PRINT " -j ", TAB$(2), "Invoke C Preprocessor"
	    PRINT " -p ", TAB$(2), "Preserve temporary files"
	    PRINT " -b ", TAB$(2), "Execute from shebang"
	    PRINT " -v ", TAB$(2), "Show version"
	    PRINT " -h ", TAB$(2), "Show help", NL$
	    END

	' Version option
	CASE "-v"
	    PRINT NL$, "BaCon version ", g_VERSION$, " - (c) Peter van Eerten - GPL v3.", NL$
	    END

	' Preserve option
	CASE "-p"
	    g_TMP_PRESERVE = 1

	' Gettext option
	CASE "-x"
	    g_XGETTEXT = 1

	' No compile option
	CASE "-n"
	    g_NO_COMPILE = 1

	' Invoke C Preprocessor
	CASE "-j"
	    g_CPP = 1

	' Shared library
	CASE "-f"
	    g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " -shared -rdynamic")
	    IF INSTR(OS$, "x86_64") THEN g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " -fPIC")
	    g_BINEXT$ = ".so"

	' use shebang
	CASE "-b"
	    g_SHEBANG = TRUE
	    g_TEMPDIR$ = "/tmp"

	' This is the sourcefile
	DEFAULT
	    g_SOURCEFILE$ = args$[i]

    END SELECT

    INCR i

WEND

IF LEFT$(g_SOURCEFILE$, 7) = "http://" THEN
    g_SOURCEFILE$ = MID$(g_SOURCEFILE$, 8)
    Download_File(g_SOURCEFILE$)
    g_SOURCEFILE$ = MID$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, "/")+1)
ELIF NOT(EQUAL(RIGHT$(g_SOURCEFILE$, 4), ".bac")) THEN
    g_SOURCEFILE$ = CONCAT$(g_SOURCEFILE$, ".bac")
END IF

IF ISFALSE(FILEEXISTS(g_SOURCEFILE$)) THEN
    PRINT "ERROR: file not found!"
    END ERROR
END IF

' Change the working directory
IF INSTR(g_SOURCEFILE$, "/") THEN CHANGEDIR MID$(g_SOURCEFILE$, 1, INSTRREV(g_SOURCEFILE$, "/")-1)

' Now create the global filenames where to write to
g_CFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".c")
g_HFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h")
STRINGARRAYFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h")
FLOATARRAYFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h")

' Check to overwrite
IF FILEEXISTS(g_CFILE$) OR FILEEXISTS(g_HFILE$) THEN
    IF FILEEXISTS(g_CFILE$) THEN DELETE FILE g_CFILE$
    IF FILEEXISTS(g_HFILE$) THEN DELETE FILE g_HFILE$
    IF FILEEXISTS(STRINGARRAYFILE$) THEN DELETE FILE STRINGARRAYFILE$
    IF FILEEXISTS(FLOATARRAYFILE$) THEN DELETE FILE FLOATARRAYFILE$
END IF

IF NOT(g_SHEBANG) THEN PRINT "Starting conversion...";

' Add to total file list
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_CFILE$)
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_HFILE$)
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", STRINGARRAYFILE$)
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", FLOATARRAYFILE$)

' Create new sourcefile
OPEN g_CFILE$ FOR WRITING AS g_CFILE

' Create basic C file
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_CFILE
WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h\"" TO g_CFILE
WRITELN "int main(int argc, const char **argv)" TO g_CFILE
WRITELN "{" TO g_CFILE
WRITELN "/* Default is: system traps signals */" TO g_CFILE
WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE
WRITELN "/* Make sure internal string buffers are empty */" TO g_CFILE
WRITELN "__b2c__sbuffer_ptr=0;" TO g_CFILE
WRITELN "__b2c__rbuffer_ptr=0;" TO g_CFILE

' Put arguments into reserved variable ARGUMENT
WRITELN "/* Setup the reserved variable 'ARGUMENT' */" TO g_CFILE
WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" TO g_CFILE
WRITELN "{__b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++;" TO g_CFILE
WRITELN "ARGUMENT", g_STRINGSIGN$, " = (char*)calloc(__b2c__arglen, sizeof(char));" TO g_CFILE
WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" TO g_CFILE
WRITELN "{strcat(ARGUMENT", g_STRINGSIGN$, ", argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT", g_STRINGSIGN$, ", \" \");}" TO g_CFILE
WRITELN "/* By default seed random generator */" TO g_CFILE
WRITELN "srandom((unsigned int)time(NULL));" TO g_CFILE
WRITELN "/* Initialize internal stackpointer */" TO g_CFILE
WRITELN "__b2c__typestack = (int*)calloc(1, sizeof(int));" TO g_CFILE
WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, sizeof(char*)); __b2c__stringstack[0] = calloc(1, sizeof(char));" TO g_CFILE
WRITELN "/* Rest of the program */" TO g_CFILE

' Create new headerfile
OPEN g_HFILE$ FOR WRITING AS g_HFILE

' Create basic H file, functions are converted using macros
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_HFILE
WRITELN "#include <stdio.h>" TO g_HFILE
WRITELN "#include <stdlib.h>" TO g_HFILE
WRITELN "#include <stdarg.h>" TO g_HFILE
WRITELN "#include <sys/time.h>" TO g_HFILE
WRITELN "#include <sys/stat.h>" TO g_HFILE
WRITELN "#include <sys/types.h>" TO g_HFILE
WRITELN "#include <sys/wait.h>" TO g_HFILE
WRITELN "#include <sys/socket.h>" TO g_HFILE
WRITELN "#include <sys/utsname.h>" TO g_HFILE
WRITELN "#include <dirent.h>" TO g_HFILE
WRITELN "#include <setjmp.h>" TO g_HFILE
WRITELN "#include <netdb.h>" TO g_HFILE
IF INSTR(OS$, "BSD") THEN
    WRITELN "#include <netinet/in.h>" TO g_HFILE
END IF
WRITELN "#include <arpa/inet.h>" TO g_HFILE
WRITELN "#include <signal.h>" TO g_HFILE
WRITELN "static jmp_buf __b2c__jump;" TO g_HFILE
WRITELN "static int __b2c__trap = 1;" TO g_HFILE
WRITELN "static int __b2c__catch_set = 0;" TO g_HFILE
WRITELN "static int ERROR = 0;" TO g_HFILE
WRITELN "static int __b2c__option_compare = 0;" TO g_HFILE
WRITELN "static int __b2c__option_memstream = 0;" TO g_HFILE
WRITELN "static int __b2c__memtype = 1;" TO g_HFILE
WRITELN "static int __b2c__collapse = 0;" TO g_HFILE
WRITELN "int __b2c__break_ctr = 0;" TO g_HFILE
WRITELN "int __b2c__break_flag = 0;" TO g_HFILE
WRITELN "int RETVAL = 0;" TO g_HFILE
WRITELN "char __b2c__chop_default[] = \"\\r\\n\\t \";" TO g_HFILE
WRITELN "char VERSION", g_STRINGSIGN$, "[] = \"", g_VERSION$, "\";" TO g_HFILE

' Add user include files
WRITELN "/* User include files */" TO g_HFILE
WRITELN g_INCFILES$ TO g_HFILE

WRITELN "/* READ/DATA include files */" TO g_HFILE
WRITELN "int __b2c__stringarray_ptr = 0;" TO g_HFILE
WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h\"" TO g_HFILE
WRITELN "int __b2c__floatarray_ptr = 0;" TO g_HFILE
WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h\"" TO g_HFILE
WRITELN "int __b2c__ctr;" TO g_HFILE

WRITELN "/* Math functions */" TO g_HFILE
WRITELN "extern double round(double __b2c__x);" TO g_HFILE
WRITELN "extern long int lrint(double __b2c__x);" TO g_HFILE
WRITELN "#include <math.h>" TO g_HFILE
WRITELN "#define SQR(__b2c__x) sqrt(__b2c__x)" TO g_HFILE
WRITELN "#define POW(__b2c__x, __b2c__y) pow(__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "#define SIN(__b2c__x) sin(__b2c__x)" TO g_HFILE
WRITELN "#define COS(__b2c__x) cos(__b2c__x)" TO g_HFILE
WRITELN "#define TAN(__b2c__x) tan(__b2c__x)" TO g_HFILE
WRITELN "#define ATN(__b2c__x) atan(__b2c__x)" TO g_HFILE
WRITELN "#define LOG(__b2c__x) log(__b2c__x)" TO g_HFILE
WRITELN "#define EXP(__b2c__x) exp(__b2c__x)" TO g_HFILE
WRITELN "#define SGN(__b2c__x) (__b2c__x == 0 ? 0 : (__b2c__x < 0 ? -1 : 1))" TO g_HFILE
WRITELN "#define ROUND(__b2c__x) lrint(__b2c__x)" TO g_HFILE
WRITELN "#define INT(__b2c__x) lrint(__b2c__x)" TO g_HFILE
WRITELN "#define MOD(__b2c__x, __b2c__y) ((long)__b2c__x % (long)__b2c__y)" TO g_HFILE
WRITELN "#define EVEN(__b2c__x) ((__b2c__x % 2 == 0) ? 1 : 0)" TO g_HFILE
WRITELN "#define ODD(__b2c__x) ((__b2c__x % 2 != 0) ? 1 : 0)" TO g_HFILE
WRITELN "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" TO g_HFILE
WRITELN "#define ABS(__b2c__x) (long)abs(__b2c__x)" TO g_HFILE
WRITELN "#define RND random()" TO g_HFILE
IF INSTR(OS$, "SunOS") THEN
    WRITELN "#define MAXRANDOM 2147483647" TO g_HFILE
ELSE
    WRITELN "#define MAXRANDOM RAND_MAX" TO g_HFILE
END IF
WRITELN "#define RANDOM(__b2c__x) ((__b2c__x != 0) ? random()/(MAXRANDOM/__b2c__x) : 0)" TO g_HFILE
WRITELN "/* Other functions */" TO g_HFILE
WRITELN "#define VAL(__b2c__x) ((__b2c__x != NULL) ? atof(__b2c__x) : 0)" TO g_HFILE
WRITELN "/* Unix functions */" TO g_HFILE
WRITELN "#include <unistd.h>" TO g_HFILE
WRITELN "#define SYSTEM(__b2c__x) do {if (__b2c__x != NULL) {RETVAL = system(__b2c__x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" TO g_HFILE
WRITELN "/* String functions */" TO g_HFILE
WRITELN "#include <string.h>" TO g_HFILE
WRITELN "char *__b2c__strndup(const char *__b2c__s, size_t __b2c__n){size_t __b2c__avail;" TO g_HFILE
WRITELN "char *__b2c__p; if (!__b2c__s) return 0; __b2c__avail = strlen(__b2c__s) + 1;" TO g_HFILE
WRITELN "if (__b2c__avail > __b2c__n + 1) __b2c__avail = __b2c__n + 1; __b2c__p = malloc(__b2c__avail);" TO g_HFILE
WRITELN "memcpy(__b2c__p, __b2c__s, __b2c__avail); __b2c__p[__b2c__avail - 1] = '\\0'; return __b2c__p;}" TO g_HFILE
WRITELN "char __b2c__input__buffer[", g_BUFFER_SIZE, "];" TO g_HFILE
WRITELN "char* __b2c__sbuffer[", g_MAX_BUFFERS, "] = { NULL };" TO g_HFILE
WRITELN "int __b2c__sbuffer_ptr;" TO g_HFILE
WRITELN "char* __b2c__rbuffer[", g_MAX_RBUFFERS, "] = { NULL };" TO g_HFILE
WRITELN "int __b2c__rbuffer_ptr;" TO g_HFILE
WRITELN "/* Temporary pointer to perform assignments */" TO g_HFILE
WRITELN "char *__b2c__assign = NULL;" TO g_HFILE
WRITELN "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL; char *__b2c__split_ptr = NULL;" TO g_HFILE
WRITELN "char *ERR", g_STRINGSIGN$, "(int);" TO g_HFILE
WRITELN "/* Functions for sort */" TO g_HFILE
WRITELN "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{return strcmp(*(char **) __b2c__a, *(char **) __b2c__b);}" TO g_HFILE
WRITELN "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{return strcmp(*(char **) __b2c__b, *(char **) __b2c__a);}" TO g_HFILE
WRITELN "/* Actual functions */" TO g_HFILE
WRITELN "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*sizeof(char));" TO g_HFILE
WRITELN "return (getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "));}" TO g_HFILE
WRITELN "#define CURDIR", g_STRINGSIGN$, " __b2c__curdir()" TO g_HFILE
WRITELN "char* __b2c__reverse(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__s)+2)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)+1);" TO g_HFILE
WRITELN "for(__b2c__i=0;__b2c__i<strlen(__b2c__s);__b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__s[strlen(__b2c__s)-1-__b2c__i];}" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define REVERSE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__reverse(x) : \"null\")" TO g_HFILE
WRITELN "char* __b2c__str(double d){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, "*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "if(floor(d) == d) snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%ld\", (long)d); else snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%.10g\", d);" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define STR", g_STRINGSIGN$, "(x) __b2c__str(x)" TO g_HFILE
WRITELN "char* __b2c__concat(char *__b2c__first, ...){char *__b2c__tmp; va_list __b2c__ap; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "if(__b2c__first != NULL) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__first)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);}" TO g_HFILE
WRITELN "else {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"\");} va_start(__b2c__ap, __b2c__first);" TO g_HFILE
WRITELN "while((__b2c__tmp = va_arg(__b2c__ap, char *)) != NULL) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__tmp)+strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])+1)*sizeof(char));" TO g_HFILE
WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__tmp);} va_end(__b2c__ap); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define CONCAT", g_STRINGSIGN$, "(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" TO g_HFILE
WRITELN "char* __b2c__left(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, (__b2c__n));" TO g_HFILE
WRITELN "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define LEFT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "char* __b2c__right(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+ strlen(__b2c__src)- __b2c__n);" TO g_HFILE
WRITELN "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define RIGHT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; long __b2c__start, __b2c__end; if(__b2c__src == NULL || strlen(__b2c__src) == 0) return(\"\");" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); va_start(__b2c__ap, __b2c__src);" TO g_HFILE
WRITELN "__b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); if(__b2c__start > strlen(__b2c__src)) return(\"\"); __b2c__end = va_arg(__b2c__ap, long); if((__b2c__end) < 0 || (__b2c__end) > strlen (__b2c__src)) __b2c__end = strlen(__b2c__src)-__b2c__start+1;" TO g_HFILE
WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(long)(__b2c__start)-1, (__b2c__end)); va_end(__b2c__ap); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define MID", g_STRINGSIGN$, "(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" TO g_HFILE
WRITELN "long __b2c__instr(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" TO g_HFILE
WRITELN "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" TO g_HFILE
WRITELN "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos - 1, __b2c__tmp);" TO g_HFILE
WRITELN "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" TO g_HFILE
WRITELN "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" TO g_HFILE
WRITELN "long __b2c__instrrev(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res = NULL; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" TO g_HFILE
WRITELN "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" TO g_HFILE
WRITELN "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); while(__b2c__res == NULL && __b2c__pos <= strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])) {" TO g_HFILE
WRITELN "__b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + strlen(__b2c__sbuffer[__b2c__sbuffer_ptr]) - __b2c__pos, __b2c__tmp); __b2c__pos+=1;}" TO g_HFILE
WRITELN "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" TO g_HFILE
WRITELN "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" TO g_HFILE
WRITELN "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define SPC", g_STRINGSIGN$, "(x) ((x > -1) ? __b2c__spc(x) : \"\")" TO g_HFILE
WRITELN "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define TAB", g_STRINGSIGN$, "(x) ((x > -1) ? __b2c__tab(x) : \"\")" TO g_HFILE
WRITELN "char* __b2c__fill(unsigned long __b2c__x, unsigned char __b2c__y){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define FILL", g_STRINGSIGN$, "(x, y) ((y > -1 && y < 256) ? __b2c__fill(x, y) : \"\")" TO g_HFILE
WRITELN "char* __b2c__chop(char *__b2c__src, ...){char *__b2c__tmp, *__b2c__str; int __b2c__i, __b2c__loc = 0; va_list __b2c__ap; if(strlen(__b2c__src) == 0) return(__b2c__src);" TO g_HFILE
WRITELN "va_start (__b2c__ap, __b2c__src); __b2c__str = va_arg (__b2c__ap, char*); if(__b2c__str == 0) __b2c__str = (char*)__b2c__chop_default; else __b2c__loc = va_arg (__b2c__ap, int); va_end (__b2c__ap);" TO g_HFILE
WRITELN "if(__b2c__loc == 0 || __b2c__loc == 1) {while (*__b2c__src != '\\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__src == *(__b2c__str+__b2c__i)) {__b2c__src++; break; } }" TO g_HFILE
WRITELN "if(__b2c__i == strlen(__b2c__str)) break;} if (*__b2c__src == '\\0') return(\"\");} __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" TO g_HFILE
WRITELN "if(__b2c__loc == 0 || __b2c__loc == 2) {while (__b2c__tmp >= __b2c__src && *__b2c__tmp != '\\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__tmp == *(__b2c__str+__b2c__i))" TO g_HFILE
WRITELN "{__b2c__tmp--; break; } } if(__b2c__i == strlen(__b2c__str)) break;} } __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define CHOP", g_STRINGSIGN$, "(...) __b2c__chop(__VA_ARGS__, 0)" TO g_HFILE
WRITELN "char* __b2c__replace(char* __b2c__x, char* __b2c__y, char* __b2c__z){" TO g_HFILE
WRITELN "char *__b2c__tmp, *__b2c__buf, *__b2c__haystack, *__b2c__dup = NULL; __b2c__sbuffer_ptr++;" TO g_HFILE
WRITELN "if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0; __b2c__haystack = strdup(__b2c__x); __b2c__dup = __b2c__haystack;" TO g_HFILE
WRITELN "__b2c__buf = calloc(1, sizeof(char)); while((__b2c__tmp = strstr(__b2c__haystack, __b2c__y)) != NULL) {*__b2c__tmp = '\\0';" TO g_HFILE
WRITELN "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + strlen(__b2c__z) + 1)*sizeof(char));" TO g_HFILE
WRITELN "strcat(__b2c__buf, __b2c__haystack);strcat(__b2c__buf, __b2c__z);__b2c__haystack = __b2c__tmp+strlen(__b2c__y);}" TO g_HFILE
WRITELN "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + 1)*sizeof(char));strcat(__b2c__buf, __b2c__haystack);" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__buf)+1)*sizeof(char));" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf);free(__b2c__buf);free(__b2c__dup);return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define REPLACE", g_STRINGSIGN$, "(x, y, z)((x!=NULL && y!=NULL && z!= NULL) ? __b2c__replace(x, y, z) : 0)" TO g_HFILE
WRITELN "#define LEN(x) ((x != NULL) ? strlen(x) : 0)" TO g_HFILE
WRITELN "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 0) ? !strcmp(__b2c__x, __b2c__y) : ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 1) ? !strcasecmp(__b2c__x, __b2c__y) : 0) )" TO g_HFILE
WRITELN "char* __b2c__getenv(char *__b2c__env){static char* __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" TO g_HFILE
WRITELN "{return \"\";} return __b2c__tmp;}" TO g_HFILE
WRITELN "#define GETENVIRON", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__getenv(x) : \"null\")" TO g_HFILE
WRITELN "#define SETENVIRON(x, y) if(x != NULL && y != NULL) setenv(x, y, 1)" TO g_HFILE
WRITELN "/* CHAR functions */" TO g_HFILE
WRITELN "#include <ctype.h>" TO g_HFILE
WRITELN "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define UCASE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__ucase(x) : \"null\")" TO g_HFILE
WRITELN "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define LCASE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__lcase(x) : \"null\")" TO g_HFILE
WRITELN "/* I/O functions */" TO g_HFILE
WRITELN "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" TO g_HFILE
WRITELN "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "long __b2c__hex2dec(char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" TO g_HFILE
WRITELN "fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return(long)(__b2c__i);}" TO g_HFILE
WRITELN "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" TO g_HFILE
WRITELN "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "/* Function FILEEXISTS contributed by Armando Rivera */ " TO g_HFILE
WRITELN "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" TO g_HFILE
WRITELN "#define FILEEXISTS(x) __b2c__fileexists(x)" TO g_HFILE
WRITELN "long __b2c__filelen(const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" TO g_HFILE
WRITELN "#define FILELEN(x) __b2c__filelen(x)" TO g_HFILE
WRITELN "long __b2c__filetype(const char *__b2c__x) {struct stat __b2c__buf; if(__b2c__x == NULL) return 0; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap)" TO g_HFILE
WRITELN "{ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if (S_ISREG(__b2c__buf.st_mode)) return 1; if (S_ISDIR(__b2c__buf.st_mode)) return 2;" TO g_HFILE
WRITELN "if (S_ISCHR(__b2c__buf.st_mode)) return 3; if (S_ISBLK(__b2c__buf.st_mode)) return 4; if (S_ISFIFO(__b2c__buf.st_mode)) return 5;" TO g_HFILE
WRITELN "if (S_ISLNK(__b2c__buf.st_mode)) return 6; if (S_ISSOCK(__b2c__buf.st_mode)) return 7; return 0;}" TO g_HFILE
WRITELN "#define FILETYPE(x) __b2c__filetype(x)" TO g_HFILE
WRITELN "long __b2c__search(FILE* __b2c__x, char* __b2c__y){long __b2c__off, __b2c__pos; char* __b2c__ptr; size_t __b2c__tot;" TO g_HFILE
WRITELN "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" TO g_HFILE
WRITELN "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" TO g_HFILE
WRITELN "__b2c__tot = fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" TO g_HFILE
WRITELN "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" TO g_HFILE
WRITELN "if(strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y))) __b2c__off = 0; fseek(__b2c__x, __b2c__pos, SEEK_SET); free(__b2c__ptr); return (--__b2c__off);}" TO g_HFILE
WRITELN "#define SEARCH(x, y) __b2c__search(x, y)" TO g_HFILE
WRITELN "char *__b2c__exec(char *__b2c__x, ...){int __b2c__r, __b2c__len, __b2c__i, __b2c__page; int __b2c__wpipe[2], __b2c__rpipe[2]; char *__b2c__str, *__b2c__ans = NULL; va_list __b2c__ap;" TO g_HFILE
WRITELN "va_start(__b2c__ap, __b2c__x); __b2c__str = va_arg (__b2c__ap, char*); va_end(__b2c__ap); if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}}" TO g_HFILE
WRITELN "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}} else if (__b2c__r == 0){" TO g_HFILE
WRITELN "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], STDIN_FILENO);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], STDOUT_FILENO);close (__b2c__rpipe[1]); __b2c__r = system (__b2c__x); if(WIFEXITED(__b2c__r)) RETVAL = WEXITSTATUS(__b2c__r); else RETVAL=0; exit(RETVAL);}" TO g_HFILE
WRITELN "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*sizeof(char) + 1);__b2c__ans = (char*)malloc(", g_BUFFER_SIZE, " *sizeof(char)); __b2c__len = 0;__b2c__page = 0;" TO g_HFILE
WRITELN "if(__b2c__str!=NULL) __b2c__i = write(__b2c__wpipe[1], __b2c__str, strlen(__b2c__str)+1); wait(&RETVAL); RETVAL = WEXITSTATUS(RETVAL); do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, ", g_BUFFER_SIZE, ");if (__b2c__i == -1 && !__b2c__trap){ERROR=30;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if (__b2c__i == 0)break;if (__b2c__len + __b2c__i > ", g_BUFFER_SIZE, " *__b2c__page + 1){__b2c__page++;__b2c__sbuffer[__b2c__sbuffer_ptr] = realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*__b2c__page + 1);" TO g_HFILE
WRITELN "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len, __b2c__ans, __b2c__i);" TO g_HFILE
WRITELN " __b2c__len += __b2c__i;} while (__b2c__i > 0); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0';close (__b2c__wpipe[1]);" TO g_HFILE
WRITELN "close (__b2c__rpipe[0]);free (__b2c__ans);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define EXEC", g_STRINGSIGN$, "(...) __b2c__exec(__VA_ARGS__, (char*)NULL)" TO g_HFILE
WRITELN "#define ENDFILE(x) feof(x)" TO g_HFILE
WRITELN "#define TELL(x) ftell(x)" TO g_HFILE
WRITELN "#define HEX", g_STRINGSIGN$, "(x) __b2c__dec2hex(x)" TO g_HFILE
WRITELN "#define DEC(x) __b2c__hex2dec(x)" TO g_HFILE
WRITELN "#define ASC(x) __b2c__char2asc(x)" TO g_HFILE
WRITELN "#define CHR", g_STRINGSIGN$, "(__b2c__x) __b2c__asc2char(__b2c__x)" TO g_HFILE
WRITELN "#define MEMTELL(x) (long)x" TO g_HFILE
WRITELN "/* Dynamic loading, errors */" TO g_HFILE
WRITELN "#include <dlfcn.h>" TO g_HFILE
WRITELN "#include <errno.h>" TO g_HFILE
WRITELN "/* GETKEY */" TO g_HFILE
WRITELN "#include <termios.h>" TO g_HFILE
WRITELN "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(STDIN_FILENO, &__b2c__oldt);" TO g_HFILE
WRITELN "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);" TO g_HFILE
WRITELN "__b2c__ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt); return __b2c__ch;} " TO g_HFILE
WRITELN "#define GETKEY __b2c__getch()" TO g_HFILE
WRITELN "long __b2c__getxy(int __b2c__type){char __b2c__asw[", g_BUFFER_SIZE, "]; struct termios __b2c__old, __b2c__new; int __b2c__len, __b2c__x, __b2c__y; ssize_t __b2c__tot;" TO g_HFILE
WRITELN "tcgetattr(STDIN_FILENO, &__b2c__old); __b2c__new = __b2c__old;__b2c__new.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__new);" TO g_HFILE
WRITELN "__b2c__tot = write(STDOUT_FILENO, \"\\033[6n\", strlen(\"\\033[6n\")); __b2c__len = read(STDIN_FILENO, __b2c__asw, ", g_BUFFER_SIZE, ");__b2c__asw[__b2c__len] = '\\0'; " TO g_HFILE
WRITELN "tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__old); sscanf(__b2c__asw, \"\\033[%d;%dR\", &__b2c__y, &__b2c__x); if (!__b2c__type) return(long)__b2c__x; return(long)__b2c__y;}" TO g_HFILE
WRITELN "#define GETX __b2c__getxy(0)" TO g_HFILE
WRITELN "#define GETY __b2c__getxy(1)" TO g_HFILE
WRITELN "long __b2c__screen(int __b2c__type){long __b2c__x; fprintf(stdout,\"\\033[s\"); fprintf(stdout,\"\\033[?25l\"); fprintf(stdout,\"\\033[999;999H\"); fflush(stdout);" TO g_HFILE
WRITELN "__b2c__x = __b2c__getxy(__b2c__type); fprintf(stdout,\"\\033[u\"); fprintf(stdout,\"\\033[?25h\"); fflush(stdout); return(__b2c__x); }" TO g_HFILE
WRITELN "#define COLUMNS __b2c__screen(0)" TO g_HFILE
WRITELN "#define ROWS __b2c__screen(1)" TO g_HFILE
WRITELN "/* Constants, logical stuff */" TO g_HFILE
WRITELN "#define PI 3.14159265" TO g_HFILE
WRITELN "#define NOT(__b2c__x) (!(__b2c__x))" TO g_HFILE
WRITELN "#define AND &&" TO g_HFILE
WRITELN "#define OR ||" TO g_HFILE
WRITELN "#define EQ ==" TO g_HFILE
WRITELN "#define IS ==" TO g_HFILE
WRITELN "#define NE !=" TO g_HFILE
WRITELN "#define ISNOT !=" TO g_HFILE
WRITELN "#define TRUE 1" TO g_HFILE
WRITELN "#define FALSE 0" TO g_HFILE
WRITELN "#define NL", g_STRINGSIGN$, " \"\\n\"" TO g_HFILE
WRITELN "#define STRING char*" TO g_HFILE
WRITELN "#define NUMBER long" TO g_HFILE
WRITELN "#define FLOATING double" TO g_HFILE
WRITELN "#define ISTRUE(__b2c__x) (__b2c__x!=0)" TO g_HFILE
WRITELN "#define ISFALSE(__b2c__x) (__b2c__x==0)" TO g_HFILE
WRITELN "#define SIZEOF(__b2c__x) sizeof(__b2c__x)" TO g_HFILE
WRITELN "/* Date and time */" TO g_HFILE
WRITELN "#include <time.h>" TO g_HFILE
WRITELN "#define NOW (long)time(NULL)" TO g_HFILE
WRITELN "long __b2c__time(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr],", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, "); ts = localtime(&__b2c__now); switch(__b2c__which) { case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%d\", ts); break;" TO g_HFILE
WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%m\", ts); break; case 3: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%Y\", ts); break;" TO g_HFILE
WRITELN "case 4: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%H\", ts); break; case 5: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%M\", ts); break;" TO g_HFILE
WRITELN "case 6: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%S\", ts); break; case 7: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%W\", ts); break;}" TO g_HFILE
WRITELN "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" TO g_HFILE
WRITELN "#define DAY(x) __b2c__time(x, 1)" TO g_HFILE
WRITELN "#define MONTH(x) __b2c__time(x, 2)" TO g_HFILE
WRITELN "#define YEAR(x) __b2c__time(x, 3)" TO g_HFILE
WRITELN "#define HOUR(x) __b2c__time(x, 4)" TO g_HFILE
WRITELN "#define MINUTE(x) __b2c__time(x, 5)" TO g_HFILE
WRITELN "#define SECOND(x) __b2c__time(x, 6)" TO g_HFILE
WRITELN "#define WEEK(x) __b2c__time(x, 7)" TO g_HFILE
WRITELN "char* __b2c__datename(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, "); ts = localtime(&__b2c__now); switch(__b2c__which){case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%A\", ts); break;" TO g_HFILE
WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%B\", ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define WEEKDAY", g_STRINGSIGN$, "(x) __b2c__datename(x, 1)" TO g_HFILE
WRITELN "#define MONTH", g_STRINGSIGN$, "(x) __b2c__datename(x, 2)" TO g_HFILE
WRITELN "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" TO g_HFILE
WRITELN "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" TO g_HFILE
WRITELN "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" TO g_HFILE
WRITELN "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" TO g_HFILE
WRITELN "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" TO g_HFILE
WRITELN "char* __b2c__os(void){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, "); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" TO g_HFILE
WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define OS", g_STRINGSIGN$, " __b2c__os()" TO g_HFILE
WRITELN "/* Peek and Poke */" TO g_HFILE
WRITELN "struct stat __b2c__sb;" TO  g_HFILE
WRITELN "void __b2c__memory__check(void* __b2c__x) {if (stat(__b2c__x, &__b2c__sb) == -1 && errno == EFAULT) {ERROR = 1;} }" TO g_HFILE
WRITELN "long __b2c__malloc(long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); switch(__b2c__memtype) {case 1: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;" TO g_HFILE
WRITELN "case 2: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(short)); break; case 3: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(int)); break;" TO g_HFILE
WRITELN "case 4: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(long)); break; case 5: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(float)); break;" TO g_HFILE
WRITELN "case 6: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(double)); break; case 7: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;}" TO g_HFILE
WRITELN "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return(long)__b2c__mem;}" TO g_HFILE
WRITELN "#define MEMORY(__b2c__x) __b2c__malloc(__b2c__x)" TO g_HFILE
WRITELN "void *__b2c__realloc(void* __b2c__x, long __b2c__y) {if(__b2c__x == NULL) return (NULL); if(!__b2c__trap) {__b2c__memory__check((char*)__b2c__x);" TO g_HFILE
WRITELN "if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } switch(__b2c__memtype) {case 1: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;" TO g_HFILE
WRITELN "case 2: __b2c__x = realloc((void*)__b2c__x, sizeof(short)*(__b2c__y+1)); break; case 3: __b2c__x = realloc((void*)__b2c__x, sizeof(int)*(__b2c__y+1)); break;" TO g_HFILE
WRITELN "case 4: __b2c__x = realloc((void*)__b2c__x, sizeof(long)*(__b2c__y+1)); break; case 5: __b2c__x = realloc((void*)__b2c__x, sizeof(float)*(__b2c__y+1)); break;" TO g_HFILE
WRITELN "case 6: __b2c__x = realloc((void*)__b2c__x, sizeof(double)*(__b2c__y+1)); break; case 7: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;}" TO g_HFILE
WRITELN "if(__b2c__x == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return (__b2c__x);}" TO g_HFILE
WRITELN "#define RESIZE(__b2c__x, __b2c__y) __b2c__realloc((void*)__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "char __b2c__peek(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" TO g_HFILE
WRITELN "short __b2c__peeks(short* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((short*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((short)*__b2c__x);}" TO g_HFILE
WRITELN "int __b2c__peeki(int* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((int*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((int)*__b2c__x);}" TO g_HFILE
WRITELN "long __b2c__peekl(long* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((long*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((long)*__b2c__x);}" TO g_HFILE
WRITELN "float __b2c__peekf(float* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((float*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((float)*__b2c__x);}" TO g_HFILE
WRITELN "double __b2c__peekd(double* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((double*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((double)*__b2c__x);}" TO g_HFILE
WRITELN "char __b2c__peekv(char* __b2c__x) {if(!__b2c__trap) {__b2c__memory__check((char*) __b2c__x); if(ERROR) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" TO g_HFILE
WRITELN "#define PEEK(__b2c__x) (__b2c__memtype==1 ? (unsigned char)__b2c__peek((char*)__b2c__x) : (__b2c__memtype==2 ? (unsigned short)__b2c__peeks((short*)__b2c__x) : (__b2c__memtype==3 ? (unsigned int)__b2c__peeki((int*)__b2c__x) : \\" TO g_HFILE
WRITELN "(__b2c__memtype==4 ? (unsigned long)__b2c__peekl((long*)__b2c__x) : ( __b2c__memtype==5 ? (float)__b2c__peekf((float*)__b2c__x) : (__b2c__memtype==6 ? (double)__b2c__peekd((double*)__b2c__x) : (unsigned char)__b2c__peekv((char*)__b2c__x) ))))))" TO g_HFILE
WRITELN "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" TO g_HFILE
WRITELN "/* Network variables and functions */" TO g_HFILE
WRITELN "struct timeval __b2c__to; struct hostent *__b2c__he;  char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; struct sockaddr_in __b2c__addr; " TO g_HFILE
WRITELN "int __b2c__result; char __b2c__data_client[", g_BUFFER_SIZE, "] = { 0 }; char __b2c__data_server[", g_BUFFER_SIZE, "] = { 0 }; int __b2c__handle;" TO g_HFILE
WRITELN "long __b2c__netpeek(int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds; struct timeval __b2c__tv; long __b2c__retval; struct termios __b2c__oldt, __b2c__newt;" TO g_HFILE
WRITELN "if(__b2c__fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &__b2c__oldt); __b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);}" TO g_HFILE
WRITELN "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = (__b2c__usec%1000)*1000; __b2c__tv.tv_sec = __b2c__usec/1000;" TO g_HFILE
WRITELN "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv); if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__fd == STDIN_FILENO){if(__b2c__retval) if(read(__b2c__fd, &__b2c__retval, 1)==0) __b2c__retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt);} return(__b2c__retval);}" TO g_HFILE
WRITELN "#define WAIT(x, y) __b2c__netpeek(x, y)" TO g_HFILE
WRITELN "char* __b2c__nethost(char* __b2c__host) {int __b2c__y; int __b2c__flag = 0; struct in_addr __b2c__address; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, ");" TO g_HFILE
WRITELN "for(__b2c__y=0; __b2c__y < strlen(__b2c__host); __b2c__y++) {if(isalpha(*(__b2c__host+__b2c__y))) {__b2c__flag = 1; break;}} if(__b2c__flag) __b2c__he = gethostbyname(__b2c__host); " TO g_HFILE
WRITELN "else {if(inet_aton(__b2c__host, &__b2c__address)) __b2c__he = gethostbyaddr((void*)&__b2c__address, sizeof(struct in_addr), AF_INET); } if (__b2c__he == NULL || __b2c__he->h_addr == NULL || __b2c__he->h_name == NULL)" TO g_HFILE
WRITELN "{if(!__b2c__trap){ERROR = 11; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR); } else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Host not found\", ", g_BUFFER_SIZE ,"-1); } else {if(__b2c__flag) {__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);" TO g_HFILE
WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__addr.sin_addr), ", g_BUFFER_SIZE, "-1);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__he->h_name, ", g_BUFFER_SIZE, "-1);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define HOST", g_STRINGSIGN$, "(__b2c__x) __b2c__nethost(__b2c__x)" TO g_HFILE
WRITELN "/* Regex */" TO g_HFILE
WRITELN "#include <regex.h>" TO g_HFILE
WRITELN "long __b2c__regex(char* __b2c__x, char* __b2c__y){regex_t __b2c__reg; int __b2c__reti; char __b2c__buf[100]; __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED|REG_NOSUB);" TO g_HFILE
WRITELN "if(!__b2c__trap && __b2c__reti){ERROR=27; fprintf(stderr, \"%s: \", ERR", g_STRINGSIGN$, "(ERROR)); regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\\n\", __b2c__buf);" TO g_HFILE
WRITELN "exit(ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 0, NULL, 0);" TO g_HFILE
WRITELN "regfree(&__b2c__reg); if( !__b2c__reti ) return (1); else return (0);}" TO g_HFILE
WRITELN "#define REGEX(x, y) __b2c__regex(x, y)" TO g_HFILE
WRITELN "/* Declare reserved variable 'ARGUMENT' */" TO g_HFILE
WRITELN "int __b2c__counter;" TO g_HFILE
WRITELN "int __b2c__arglen = 0;" TO g_HFILE
WRITELN "char *ARGUMENT", g_STRINGSIGN$, ";" TO g_HFILE
WRITELN "/* Initialize stack arrays and pointer */" TO g_HFILE
WRITELN "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" TO g_HFILE
WRITELN "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" TO g_HFILE
WRITELN "int __b2c__stackptr = 0;" TO g_HFILE
' Signal function
WRITELN "/* Signal trapping activated with TRAP */" TO g_HFILE
WRITELN "void __b2c__catch_signal(int sig){" TO g_HFILE
WRITELN "switch (sig) {case SIGABRT: fprintf(stderr, \"ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.\\n\"); break;" TO g_HFILE
WRITELN "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\\n\"); break;" TO g_HFILE
WRITELN "case SIGSEGV: fprintf(stderr, \"ERROR: signal for SEGMENTATION FAULT received - memory invalid or array out of bounds? Try to compile the program with TRAP LOCAL to find the cause.\\n\"); break;" TO g_HFILE
WRITELN "case SIGILL: fprintf(stderr, \"ERROR: signal for ILLEGAL INSTRUCTION received - executing the program on other hardware? Try to recompile the program from scratch.\\n\"); break;} exit(sig);}" TO g_HFILE
' Makedir function
WRITELN "int __b2c__makedir(char* __b2c__in){char *__b2c__i, *__b2c__dir; if(__b2c__in == NULL || strlen(__b2c__in)==0) return 0; if(*__b2c__in != '/'){__b2c__dir = (char*)malloc((strlen(__b2c__in)+2)*sizeof(char));" TO g_HFILE
WRITELN "strncpy(__b2c__dir, \"./\", 2); __b2c__dir = strcat(__b2c__dir, __b2c__in);} else __b2c__dir = strdup(__b2c__in); __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\\0') __b2c__i++;" TO g_HFILE
WRITELN "if(*__b2c__i == '/') {*__b2c__i = '\\0'; mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); *__b2c__i = '/';} else if (*__b2c__i == '\\0') mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);" TO g_HFILE
WRITELN "if(errno != EEXIST && errno != 0) {free(__b2c__dir); return errno;} } while (*__b2c__i != '\\0'); free(__b2c__dir); return 0;}" TO g_HFILE
' Add error function
WRITELN "/* Initialize error function */" TO g_HFILE
WRITELN "char *ERR", g_STRINGSIGN$, "(int __b2c__nr){static char __b2c__warn[", g_BUFFER_SIZE, "] = { 0 }; const char* __b2c__err;" TO g_HFILE
WRITELN "switch(__b2c__nr){" TO g_HFILE
WRITELN "case 0: strcpy(__b2c__warn,\"Success\"); break;" TO g_HFILE
WRITELN "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 3: strcpy(__b2c__warn, \"Could not open library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" TO g_HFILE
WRITELN "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" TO g_HFILE
WRITELN "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" TO g_HFILE
WRITELN "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" TO g_HFILE
WRITELN "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" TO g_HFILE
WRITELN "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" TO g_HFILE
WRITELN "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "}; ERROR = 0; return(__b2c__warn);}" TO g_HFILE
WRITELN "/* User program definitions */" TO g_HFILE

' Set fileposition for search in header file
g_HEADER_SEARCHPOS = FILELEN(g_HFILE$)

' Initialize the arrayfiles for DATA statement
OPEN STRINGARRAYFILE$ FOR WRITING AS STRINGARRAYFILE
WRITELN "char* __b2c__stringarray[] = {" TO STRINGARRAYFILE
OPEN FLOATARRAYFILE$ FOR WRITING AS FLOATARRAYFILE
WRITELN "double __b2c__floatarray[] = {" TO FLOATARRAYFILE

' There are no imported symbols yet
LET g_IMPORTED$ = ""

' Check if the C Preprocessor needs to run
IF ISTRUE(g_CPP) THEN
    IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN
	SYSTEM CONCAT$("cpp -P -w ", g_SOURCEFILE$, " ", g_SOURCEFILE$, ".cpp")
	FEED$ = CONCAT$(g_SOURCEFILE$, ".cpp")
	g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_SOURCEFILE$, ".cpp")
    ELSE
	PRINT "ERROR: the C Preprocessor 'cpp' not found on this system! Exiting..."
	END 1
    END IF
ELSE
    FEED$ = g_SOURCEFILE$
END IF
LET g_CURFILE$ = MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1)

' Initialize
LET total$ = ""
LET g_COUNTER = 1

' Read source program
OPEN FEED$ FOR READING AS g_SOURCEFILE

WHILE NOT(ENDFILE(g_SOURCEFILE)) DO

    IF NOT(g_SHEBANG) THEN PRINT "\rStarting conversion... ", g_COUNTER, "   ";

    READLN line$ FROM g_SOURCEFILE

    ' Line is not empty?
    IF NOT(ENDFILE(g_SOURCEFILE)) AND LEN(line$) > 0 THEN

	IF EQUAL(RIGHT$(line$, 2), " \\") AND NOT(EQUAL(LEFT$(line$, 3), "REM")) AND NOT(EQUAL(LEFT$(line$, 1), CHR$(39))) THEN
	    total$ = CONCAT$(total$, LEFT$(line$, LEN(line$) - 2))
	ELSE
	    WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE
	    WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE
	    total$ = CHOP$(CONCAT$(total$, line$))
	    IF NOT(EQUAL(LEFT$(total$, 3), "REM")) AND NOT(EQUAL( LEFT$(total$, 1), CHR$(39) )) THEN
		Tokenize(total$)
	    END IF
	    LET total$ = ""
	END IF
    ENDIF

    INCR g_COUNTER
WEND

CLOSE FILE g_SOURCEFILE

' Check if enclosed IF/ELIF/ELSE needs to be closed
IF g_IF_PARSE IS 1 THEN WRITELN "}" TO g_CFILE

' Finalize main C-file
WRITELN "__B2C__PROGRAM__EXIT:" TO g_CFILE
WRITELN "return 0;" TO g_CFILE
WRITELN "}" TO g_CFILE

' Finalize STRING ARRAY file for DATA
WRITELN " \"\" };" TO STRINGARRAYFILE

' Finalize FLOAT ARRAY file for DATA
WRITELN " 0.0};" TO FLOATARRAYFILE

' Include functions and subs
SPLIT CHOP$(g_INCLUDE_FILES$) BY " " TO incfiles$ SIZE dim
FOR i = 1 TO dim
    IF LEN(incfiles$[i]) > 0 THEN WRITELN "#include \"", incfiles$[i], CHR$(34) TO g_HFILE
NEXT

' Close all filehandles
CLOSE FILE FLOATARRAYFILE
CLOSE FILE STRINGARRAYFILE
CLOSE FILE g_HFILE
CLOSE FILE g_CFILE

IF NOT(g_SHEBANG) THEN PRINT "\rStarting conversion... done.   "

' Start indentation
IF ISTRUE(g_TMP_PRESERVE) THEN
    IF ISTRUE(LEN(EXEC$("which indent 2>/dev/null"))) THEN
	PRINT "Applying indentation... ";
	SPLIT CHOP$(g_TMP_FILES$) BY " " TO tmpfiles$ SIZE dim
	FOR i = 1 TO dim
	    IF NOT(REGEX(tmpfiles$[i], ".*\\.cpp")) THEN
		IF ISTRUE(INSTR(OS$, "Darwin")) OR ISTRUE(INSTR(OS$, "BSD")) THEN
		    RENAME tmpfiles$[i] TO CONCAT$(tmpfiles$[i], ".BAK")
		    SYSTEM CONCAT$("indent ", tmpfiles$[i], ".BAK ", tmpfiles$[i])
		    DELETE FILE CONCAT$(tmpfiles$[i], ".BAK")
		ELSE
		    SYSTEM CONCAT$("indent ", tmpfiles$[i])
		    DELETE FILE CONCAT$(tmpfiles$[i], "~")
		END IF
	    END IF
	NEXT i
	PRINT "done."
    ELSE
	PRINT "WARNING: 'indent' not found on this system!"
	PRINT "Generated source code cannot be beautified."
    END IF
END IF

' Check if we need to run xgettext
IF g_XGETTEXT THEN
    IF ISTRUE(LEN(EXEC$("which xgettext 2>/dev/null"))) THEN
	PRINT "Executing xgettext... ";
	SYSTEM CONCAT$("xgettext -d ", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), " -s -o ", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), ".pot ", g_TMP_FILES$)
	IF NOT(FILEEXISTS(CONCAT$(LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), ".pot"))) THEN
	    PRINT "WARNING: catalog file not created!"
	ELSE
	    PRINT "done."
	END IF
    ELSE
	PRINT "WARNING: 'xgettext' not found on this system!"
    END IF
END IF

' Start compilation
IF ISFALSE(g_NO_COMPILE) THEN

    IF ISFALSE(LEN(EXEC$(CONCAT$("which ", g_CCNAME$, " 2>/dev/null")))) THEN
	PRINT "WARNING: '", g_CCNAME$, "' not found on this system!"
	PRINT "Generated source code cannot be compiled."
	END 0
    END IF

    ' Make sure GCC uses English localization
    SETENVIRON "LANG", "C"

    IF NOT(g_SHEBANG) THEN
	PRINT "Starting compilation... ";
	SYSTEM CONCAT$(g_CCNAME$, " ", g_CCFLAGS$, " -o ", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, " ", g_CFILE$, " ", g_LDFLAGS$, " > ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log 2>&1")
    ELSE
	SYSTEM CONCAT$(g_CCNAME$, " ", g_CCFLAGS$, " -o ", CONCAT$(g_TEMPDIR$, "/", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4)), g_BINEXT$, " ", g_CFILE$, " ", g_LDFLAGS$, " > ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log 2>&1")
    END IF

    ' Add temp file
    g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log")

    IF ISFALSE(FILELEN(CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log"))) THEN
	IF g_SHEBANG THEN
	    SYSTEM CONCAT$(g_TEMPDIR$, "/", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4))
	ELSE
	    PRINT "done."
	    PRINT "Program '", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, "' ready."
	END IF
    ELSE
	' Only print first error
	PRINT "Compiler emits messages!"
	OPEN CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log") FOR READING AS errlog
	WHILE NOT(ENDFILE(errlog)) DO
	    READLN g_ERROR$ FROM errlog
	    IF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: error\\:") THEN
		g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTR(g_ERROR$, "error:") + 6))
		g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "error:") - 1)
		BREAK
	    ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "Error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: Error\\:") THEN
		g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTRREV(g_ERROR$, ":") + 1))
		g_FILE_LINE$ = MID$(g_ERROR$, INSTR(g_ERROR$, "Error: ") + 7)
		BREAK
	    ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "warning:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: warning\\:") THEN
		g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTR(g_ERROR$, "warning:") + 8))
		g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "warning:") - 1)
		BREAK
	    ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, ":")) AND REGEX(g_ERROR$, "[0-9]+\\:") THEN
		g_ERRORTXT$ = CONCAT$("Cause:", NL$, TAB$(1), MID$(g_ERROR$, INSTRREV(g_ERROR$, ":") + 1))
		g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTRREV(g_ERROR$, ":") - 1)
		BREAK
	    END IF
	WEND
	CLOSE FILE errlog

	' Restore $-symbol if there is any
	g_ERRORTXT$ = REPLACE$(g_ERRORTXT$, g_STRINGSIGN$, "$")

	' Get the file where the error is
	g_FILE$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":") - 1)
	' Tru64Unix helper
	g_FILE$ = MID$(g_FILE$, 1, INSTR(g_FILE$, ",") - 1)

	' Non-gcc or parse problem (file does not exist)
	IF ISFALSE(LEN(g_ERROR$)) OR ISTRUE(INSTR(g_CCFLAGS$, "Wall")) OR NOT(FILEEXISTS(g_FILE$)) THEN
	    PRINT
	    SYSTEM CONCAT$("cat ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log")
	    PRINT
	ELSE
	    ' Get the error string from the logfile
	    IF INSTR(g_FILE_LINE$, "line") THEN
		g_LINE = VAL(MID$(g_FILE_LINE$, INSTR(g_FILE_LINE$, "line") + 4))
	    ELSE
		g_LINE = VAL(MID$(g_FILE_LINE$, INSTR(g_FILE_LINE$, ":") + 1))
	    END IF
	    ' Initiate error file name and error line in C code
	    g_FEED$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":")-1)
	    g_CURLINE$ = CONCAT$(STR$(g_LINE), " ")
	    g_COUNTER = 1
	    OPEN g_FILE$ FOR READING AS errlog
	    WHILE NOT(ENDFILE(errlog)) DO
		READLN line$ FROM errlog
		IF INSTR(line$, "BACON LINE") AND INSTR(line$, "noparse") THEN
		    g_CURLINE$ = MID$(line$, INSTR(line$, "BACON LINE") + 10)
		    g_FEED$ = MID$(line$, INSTR(line$, "noparse") + 7)
		    g_FEED$ = CHOP$(MID$(g_FEED$, 1, INSTR(g_FEED$, " BACON LINE")))
		END IF
		IF g_COUNTER IS g_LINE THEN
		    COUNTER = 1
		    OPEN g_FEED$ FOR READING AS g_SOURCEFILE
		    WHILE NOT(ENDFILE(g_SOURCEFILE)) DO
			READLN line$ FROM g_SOURCEFILE
			IF COUNTER IS VAL(MID$(g_CURLINE$, 1, INSTRREV(g_CURLINE$, " "))) THEN
			    PRINT NL$, "Problem:", NL$, TAB$(1), " file '", g_FEED$, "' line ", COUNTER, ": ", CHOP$(line$)
			    PRINT g_ERRORTXT$, NL$
			    BREAK
			END IF
			INCR COUNTER
		    WEND
		    CLOSE FILE g_SOURCEFILE
		    BREAK
		END IF
		INCR g_COUNTER
	    WEND
	    CLOSE FILE errlog
	END IF
	' Preserve temp files
	g_TMP_PRESERVE = 1
    END IF
END IF

' Cleanup
IF ISFALSE(g_TMP_PRESERVE) THEN
    SPLIT CHOP$(g_TMP_FILES$) BY " " TO tmpfiles$ SIZE dim
    FOR i = 1 TO dim
	SYSTEM CONCAT$("rm ", tmpfiles$[i])
    NEXT i
ELIF g_CPP IS 1 THEN
    RENAME CONCAT$(g_SOURCEFILE$, ".cpp") TO CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".cpp")
END IF
